home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / util / gnu / oleo_src.lha / src / io_term.c < prev    next >
C/C++ Source or Header  |  1992-08-18  |  80KB  |  3,817 lines

  1. /*    Copyright (C) 1990 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 1, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include <ctype.h>
  20. #include <errno.h>
  21. #include <fcntl.h>
  22. #include <stdio.h>
  23. #include <signal.h>
  24.  
  25. #ifdef I_IOCTL
  26. #include <sys/ioctl.h>
  27. #endif
  28.  
  29. #include "funcdef.h"
  30.  
  31. #define obstack_chunk_alloc ck_malloc
  32. #define obstack_chunk_free free
  33. #include "obstack.h"
  34.  
  35. #ifdef __TURBOC__
  36. #define RCFILE "oleo.rc"
  37. #else
  38. #define RCFILE ".oleorc"
  39. #endif
  40.  
  41. #include "sysdef.h"
  42.  
  43. #include "global.h"
  44. #include "cell.h"
  45. #include "kbd.h"
  46.  
  47. #define CTRL(X) ((X)&037)
  48.  
  49. #define LINE_MIN 28
  50.  
  51. #ifdef __TURBOC__
  52. #define TIMER_MULT    10000
  53. #else
  54. #if defined(NO_UALARM) && !defined(SETITIMER)
  55. #define TIMER_MULT     1/10
  56. #else
  57. #define TIMER_MULT   100000
  58. #endif
  59. #endif
  60.  
  61. /* Structures for this file */
  62.  
  63. /* for func_flags */
  64. #define NONTOP    0x1
  65. #define TOPLN    0x2
  66.  
  67. #define ALL    0x3
  68.  
  69.  
  70. #define WTH_CHR 0x4
  71. #define BRK    0x8
  72. #define NC    0x10
  73.  
  74. struct line {
  75.     int alloc;
  76.     char *buf;
  77. };
  78.  
  79. struct macro {
  80.     struct macro *mac_prev;
  81.     unsigned char *mac_exe;
  82.     int mac_flags;
  83.     CELLREF mac_row, mac_col;
  84.     struct rng mac_rng;
  85. };
  86.  
  87. /* External spreadsheet functions */
  88.  
  89. /* utils.c */
  90. extern char *char_to_string EXT1(char);
  91. extern int string_to_char EXT1(char **);
  92. extern FILE *xopen_with_backup EXT2(const char *,const char *);
  93. extern int xclose EXT1(FILE *);
  94. extern char *err_msg EXT0();
  95. extern char *mk_sprintf EXT1N(char *);
  96.  
  97. extern void init_mem EXT0();
  98. extern void init_eval EXT0();
  99. extern void init_refs EXT0();
  100. extern void init_cells EXT0();
  101.  
  102. extern void panic_read_file EXT2(FILE *,int);
  103. extern void panic_write_file EXT2(FILE *,struct rng *);
  104. extern  int panic_set_options EXT2(int, char *);
  105. extern void panic_show_options EXT0();
  106.  
  107. #ifdef USE_DLD
  108.     /* If we're using dynamic linking, we get the names of the
  109.        functions to call by prepending the basename of save_name onto
  110.            _read_file
  111.            _write_file
  112.            _set_options
  113.            _show_options
  114.        so, if the file is sylk.o , the functions are named
  115.            sylk_read_file
  116.            sylk_write_file
  117.            sylk_set_options
  118.            sylk_show_options
  119. */
  120. char *io_name;
  121.  
  122. #else
  123.  
  124. extern void sylk_read_file EXT2(FILE *,int);
  125. extern void sylk_write_file EXT2(FILE *,struct rng *);
  126. extern  int sylk_set_options EXT2(int, char *);
  127. extern void sylk_show_options EXT0();
  128.  
  129. extern void sc_read_file EXT2(FILE *,int);
  130. extern void sc_write_file EXT2(FILE *,struct rng *);
  131. extern  int sc_set_options EXT2(int, char *);
  132. extern void sc_show_options EXT0();
  133.  
  134. extern void list_read_file EXT2(FILE *,int);
  135. extern void list_write_file EXT2(FILE *,struct rng *);
  136. extern  int list_set_options EXT2(int, char *);
  137. extern void list_show_options EXT0();
  138.  
  139. /* extern char sl_sep; */
  140.  
  141. #endif
  142.  
  143. /* regions.c */
  144. extern void set_rng EXT5(struct rng *, CELLREF, CELLREF, CELLREF, CELLREF);
  145. extern void lock_region EXT2(struct rng *, int);
  146. extern void format_region EXT3(struct rng *, int, int);
  147. extern unsigned short print_width;
  148.  
  149. /* ref.c */
  150. extern int eval_next_cell EXT0();
  151. extern struct var *find_var EXT2(char *, int);
  152. extern timer_active;
  153.  
  154. /* io_utils.c */
  155. extern void get_usr_stats EXT2(int, char **);
  156. extern void set_usr_stats EXT2(int, char **);
  157.  
  158. /* io_disp.c */
  159. extern void redisp EXT0();
  160. extern void open_display EXT1(int);
  161. extern void clear_top_before EXT0();
  162. extern void clear_top_after EXT0();
  163. extern void close_display();
  164. extern void disp_scrn EXT0();
  165. extern int get_chr_prompt EXT1(char *);
  166. extern void recenter_cur_win EXT0();
  167. extern void recenter_all_win EXT0();
  168. extern void cur_status EXT0();
  169. extern int move_cell_cursor EXT2(CELLREF, CELLREF);
  170. extern int get_inp_line EXT2(char *, struct line  *);
  171.  
  172. /* utils.c */
  173. extern char *myname;
  174. extern int __make_backups;
  175. extern int __backup_by_copying;
  176.  
  177.  
  178.     /* Routines for manipulating 'struct line's */
  179. void set_line EXT2(struct line *, char *);
  180.  
  181.     /* Terminal I/O functions */
  182. int get_chr EXT0();
  183.  
  184. static unsigned char real_get_chr EXT0();
  185.  
  186.     /* Routines for manipulating key bindings */
  187. static void do_bind_key EXT4(struct keymap *, int, unsigned char, unsigned char);
  188. static void desc_map EXT1(struct keymap *);
  189.  
  190.     /* File I/O functions */
  191. static FILE *open_file EXT3(char *, struct line *, char *);
  192. static void close_file EXT2(struct line *, FILE *);
  193.  
  194.     /* Routines for putting info into 'struct rng's */
  195. static int get_two_ranges EXT4(char *, struct rng *, struct rng *, struct line *);
  196. static FILE * get_range_and_file EXT3(char *, struct rng *, struct line *);
  197. static int get_a_range EXT3(char *,struct rng *,struct line *);
  198. static int get_abs_rng EXT2(char **, struct rng *);
  199.  
  200. static void sprint_line EXT2N(struct line *, char *);
  201.  
  202.     /* Routines for converting text<-->cell_format */
  203. static int str_to_fmt EXT1(char *);
  204.  
  205.     /* Routines for converting text<-->cell_jst */
  206. static int chr_to_jst EXT1(int);
  207.  
  208.     /* Routines for implementing user commands */
  209. int global_cmd EXT1(int);
  210.  
  211. void set_options EXT1(char *);
  212.  
  213.     /* Backends for other functions */
  214. static int do_set_option EXT1(char *);
  215.  
  216.  
  217.         /* Spreadsheet (global) functions declared in this file */
  218.  
  219.  
  220. int main EXT2(int, char **);
  221.  
  222. void map_chr EXT1(int);
  223.  
  224. extern void clear_spreadsheet EXT0();
  225.  
  226. void pr_cell EXT3(CELLREF, CELLREF, CELL *);
  227.  
  228. char *cell_name EXT2(CELLREF, CELLREF);
  229. char *range_name EXT1(struct rng *);
  230.  
  231. char *fmt_to_str EXT1(int);
  232. char *jst_to_str EXT1(int);
  233.  
  234. #ifdef A0_REFS
  235. char *col_to_str EXT1(CELLREF);
  236. #endif
  237.  
  238. const int colmagic[] = {
  239.      0, 0, 1,-1, 1,-1, 1,-1, 0};
  240. const int rowmagic[] = {
  241.     -1, 1, 0, 0,-1,-1, 1, 1, 0};
  242.  
  243. char * ename[] = {
  244.     "#WHAT?",
  245.     "#ERROR",    "#BAD_INPUT",    "#NON_NUMBER",    "#NON_STRING",
  246.     "#NON_BOOL",    "#NON_RANGE",    "#OUT_OF_RANGE","#NO_VALUES",
  247.     "#DIV_BY_ZERO",    "#BAD_NAME",    "#NOT_AVAIL",    "#PARSE_ERROR",
  248.     "#NEED_OPEN",   "#NEED_CLOSE",  "#NEED_QUOTE",  "#UNK_CHAR",
  249.     "#UNK_FUNC",
  250.     0
  251. };
  252.  
  253. const char tname[] = "#TRUE";
  254. const char fname[] = "#FALSE";
  255.  
  256.  
  257. int cur_chr;
  258. struct cmd_func *cur_cmd;
  259. unsigned char cur_vector;
  260.  
  261. /* User settable options */
  262. int bkgrnd_recalc = 1;
  263. int auto_recalc = 1;
  264. /* Original value is 10 seconds/tick */
  265. unsigned signal_ticks = 10 * TIMER_MULT;
  266.  
  267. void (*read_file) EXT2(FILE *,int)           = panic_read_file;
  268. void (*write_file) EXT2(FILE *,struct rng *) = panic_write_file;
  269. int (*set_file_opts) EXT2(int, char *)         = panic_set_options;
  270. void (*show_file_opts) EXT0()             = panic_show_options;
  271.  
  272. int n_bound_macros;
  273. struct rng *bound_macros;
  274. int bound_macro_vec;
  275.  
  276. char *macro_func_arg = 0;
  277.  
  278. /* This variable is non-zero if the spreadsheet has been changed in any way */
  279. int modified = 0;
  280.  
  281. CELLREF setrow,
  282.     setcol;
  283.  
  284. CELLREF curow = MIN_ROW,
  285.     cucol = MIN_COL;
  286.  
  287. CELLREF mkrow = NON_ROW,
  288.     mkcol = NON_COL;
  289.  
  290. struct rng mkrng;
  291.  
  292. /* CELLREF srl,srh,scl,sch; */
  293.  
  294. unsigned int how_many = 1;
  295.  
  296. static struct macro *rmac = 0;
  297. static struct obstack macro_stack;
  298.  
  299. static unsigned char *making_macro;
  300. static unsigned char *making_macro_start;
  301. static unsigned int making_macro_size;
  302.  
  303. /* If 2, clear the top line before reading a character */
  304. /* if 1, clear it after reading a char */
  305. int topclear = 0;
  306.  
  307. struct line val_line;
  308. struct line fmt_line;
  309. struct line wid_line;
  310.  
  311. /* Lines 'a' through 'z' */
  312. struct line in_line[26];
  313.  
  314. unsigned short default_width=8;
  315. int default_jst = JST_LFT;
  316. int default_fmt = FMT_GEN;
  317. int default_lock = LCK_UNL;
  318.  
  319. #ifndef __TURBOC__
  320. char buf[BUFSIZ];
  321. int term_flag;
  322.  
  323. void got_sigio EXT1(int);
  324. #endif
  325. static void got_sigint EXT1(int);
  326.  
  327. extern char print_buf[];
  328.  
  329.  
  330. struct keymap **the_maps;
  331. char **map_names;
  332. int num_maps;
  333.  
  334. struct cmd_func **the_funcs;
  335. int num_funcs;
  336.  
  337. /* Keymap stuff:  This is the 'main' keymap */
  338.  
  339. #define GO_UP_CMD    1        /* We want these-all to be low */
  340. #define GO_DN_CMD    2        /* numbers so that rowmagic and */
  341. #define GO_RT_CMD    3        /* colmagic can be small arrays */
  342. #define GO_LF_CMD    4        /* Also note that GO, SCR, and  */
  343. #define GO_UPRT_CMD    5        /* MAGIC mumble must all be in  */
  344. #define GO_UPLF_CMD    6        /* the same order, and they     */
  345. #define GO_DNRT_CMD    7        /* must all agree with rowmagic */
  346. #define GO_DNLF_CMD    8        /* and colmagic */
  347.  
  348. #define SCR_UP_CMD    9
  349. #define SCR_DN_CMD    10
  350. #define SCR_RT_CMD    11
  351. #define SCR_LF_CMD    12
  352. #define SCR_UPRT_CMD    13
  353. #define SCR_UPLF_CMD    14
  354. #define SCR_DNRT_CMD    15
  355. #define SCR_DNLF_CMD    16
  356.  
  357. #define SCAN_UP_CMD    17
  358. #define SCAN_DN_CMD    18
  359. #define SCAN_RT_CMD    19
  360. #define SCAN_LF_CMD    20
  361.  
  362. #define BREAK_CMD    21
  363. #define RECENTER_CMD    22
  364. #define SET_OPT_CMD    23
  365. #define SET_DEF_CMD    24
  366. #define QUIT_CMD    25
  367. #define REDRAW_CMD    26
  368. #define USR_FMT_CMD    27
  369.  
  370. #define SET_VAR_CMD    28
  371. #define SHO_VAR_CMD    29
  372. #define SHO_ALL_VAR_CMD    30
  373.  
  374. #define RECALC_CMD    31
  375. #define BIND_KEY_CMD    32
  376. #define DESC_KEY_CMD    33
  377. #define READ_KEY_CMD    34
  378. #define SAVE_KEY_CMD    35
  379.  
  380. #define WRITE_ALL_CMD    36
  381. #define READ_ALL_CMD    37
  382. #define READ_MERGE_CMD    38
  383. #define KILL_ALL_CMD    39
  384.  
  385. #define COPY_REG    40
  386. #define COPY_VAL_REG    41
  387. #define FORMAT_REG    42
  388. #define MOVE_REG    43
  389. #define PRINT_REG    44
  390. #define SORT_REG    45
  391. #define WRITE_REG    46
  392. #define KILL_REG    47
  393.  
  394. #define START_MACRO    48
  395. #define EXECUTE_MACRO    49
  396. #define INTERACT_MACRO    50
  397.  
  398. #define GOTO_CMD    51
  399. #define SET_MARK_CMD    52
  400. #define EDIT_CELL    53
  401. #define EDIT_VAL_CELL    54
  402. #define FORMAT_CELL    55
  403. #define KILL_CELL    56
  404. #define NEW_DEF_CELL    57
  405.  
  406. #define DIGIT_0        58
  407. #define DIGIT_1        59
  408. #define DIGIT_2        60
  409. #define DIGIT_3        61
  410. #define DIGIT_4        62
  411. #define DIGIT_5        63
  412. #define DIGIT_6        64
  413. #define DIGIT_7        65
  414. #define DIGIT_8        66
  415. #define DIGIT_9        67
  416.  
  417. #define NEW_CELL    68
  418.  
  419. #define SHOW_OPT_CMD    69
  420.  
  421. #define OPEN_WIN_CMD    70
  422. #define CLOSE_WIN_CMD    71
  423. #define GOTO_WIN_CMD    72
  424.  
  425. #define END_MACRO    73
  426. #define MK_KEYMAP    74
  427.  
  428. #ifdef TEST
  429. #define DEBUG_CMD    75
  430.  
  431. #endif
  432.  
  433. static struct key main_keys_1[] = {
  434.     { 0,    SET_MARK_CMD },        /* ^@ */
  435.     { 0,    UNBOUND },
  436.     { 0,    GO_LF_CMD },
  437.     { 0,    UNBOUND },
  438.     { 0,    UNBOUND },
  439.     { 0,    UNBOUND },        /* ^E */
  440.     { 0,    GO_RT_CMD },
  441.     { 0,    BREAK_CMD },
  442.     { 0,    UNBOUND },
  443.     { 0,    UNBOUND },
  444.     { 0,    UNBOUND },        /* ^J */
  445.     { 0,    UNBOUND },
  446.     { 0,    RECENTER_CMD },
  447.      { 0,    UNBOUND },
  448.     { 0,    GO_DN_CMD },
  449.     { 0,    UNBOUND },        /* ^O */
  450.     { 0,    GO_UP_CMD },
  451.     { 0,    UNBOUND },
  452.     { 0,    REDRAW_CMD },
  453.     { 0,    UNBOUND },
  454.     { 0,    UNBOUND },        /* ^T */
  455.     { 0,    UNBOUND },
  456.     { 0,    SHO_ALL_VAR_CMD },
  457.     { 0,    UNBOUND },
  458.     { 0,    KILL_ALL_CMD },
  459.     { 0,    UNBOUND },        /* ^Y */
  460.     { 0,    UNBOUND },
  461.     { 255,    META_MAP },        /* ^[ */
  462.     { 0,    UNBOUND },        /* ^\ */
  463.     { 0,    UNBOUND },        /* ^] */
  464.     { 0,    UNBOUND },        /* ^^ */
  465.     { 0,    UNBOUND },        /* ^_ */
  466.     { 0,    NEW_CELL },        /* space */
  467.     { 0,    RECALC_CMD },        /* ! */
  468.     { 0,    NEW_CELL },        /* " */
  469.     { 0,    NEW_CELL },        /* # */
  470.     { 0,    NEW_CELL },        /* $ */
  471.     { 0,    UNBOUND },        /* % */
  472.     { 0,    UNBOUND },        /* & */
  473.     { 0,    UNBOUND },        /* ' */
  474.     { 0,    NEW_CELL },        /* ( */
  475.     { 0,    UNBOUND },        /* ) */
  476.     { 0,    UNBOUND },        /* * */
  477.     { 0,    NEW_CELL },        /* + */
  478.     { 0,    UNBOUND },        /* , */
  479.     { 0,    NEW_CELL },        /* - */
  480.     { 0,    NEW_CELL },        /* . */
  481.     { 0,    UNBOUND },        /* / */
  482.     { 0,    NEW_CELL },        /* 0 */
  483.     { 0,    NEW_CELL },        /* 1 */
  484.     { 0,    NEW_CELL },        /* 2 */
  485.     { 0,    NEW_CELL },        /* 3 */
  486.     { 0,    NEW_CELL },        /* 4 */
  487.     { 0,    NEW_CELL },        /* 5 */
  488.     { 0,    NEW_CELL },        /* 6 */
  489.     { 0,    NEW_CELL },        /* 7 */
  490.     { 0,    NEW_CELL },        /* 8 */
  491.     { 0,    NEW_CELL },        /* 9 */
  492.     { 0,    BIND_KEY_CMD },        /* : */
  493.     { 0,    DESC_KEY_CMD },        /* ; */
  494.     { 0,    UNBOUND },        /* < */
  495.     { 0,    NEW_DEF_CELL },        /* = */
  496.     { 0,    UNBOUND },        /* > */
  497.     { 0,    UNBOUND },        /* ? */
  498.     { 0,    NEW_CELL },        /* @ */
  499.     { 0,    UNBOUND },        /* A */
  500.     { 0,    SCR_DNLF_CMD },
  501.     { 0,    COPY_VAL_REG },
  502.     { 0,    UNBOUND },
  503.     { 0,    EDIT_VAL_CELL },
  504.     { 0,    FORMAT_REG },        /* F */
  505.     { 0,    UNBOUND },
  506.     { 0,    SCR_LF_CMD },
  507.     { 0,    UNBOUND },
  508.     { 0,    SCR_DN_CMD },
  509.     { 0,    SCR_UP_CMD },        /* K */
  510.     { 0,    SCR_RT_CMD },
  511.     { 0,    UNBOUND },
  512.     { 0,    SCR_DNRT_CMD },
  513.     { 0,    SHOW_OPT_CMD },
  514.     { 0,    UNBOUND },        /* P */
  515.     { 0,    QUIT_CMD },
  516.     { 0,    READ_MERGE_CMD },
  517.     { 0,    UNBOUND },
  518.     { 0,    UNBOUND },
  519.     { 0,    SCR_UPRT_CMD },        /* U */
  520.     { 0,    SHO_VAR_CMD },
  521.     { 0,    WRITE_REG },
  522.     { 0,    KILL_REG },
  523.     { 0,    SCR_UPLF_CMD },
  524.     { 0,    UNBOUND },        /* Z */
  525.     { 0,    UNBOUND },        /* [ */
  526.     { 0,    UNBOUND },        /* \ */
  527.     { 0,    UNBOUND },        /* ] */
  528.     { 0,    UNBOUND },        /* ^ */
  529.     { 0,    UNBOUND },        /* _ */
  530.     { 0,    UNBOUND },        /* ` */
  531.     { 0,    UNBOUND },        /* a */
  532.     { 0,    GO_DNLF_CMD },
  533.     { 0,    COPY_REG },
  534.     { 0,    SET_DEF_CMD },
  535.     { 0,    EDIT_CELL },
  536.     { 0,    FORMAT_CELL },        /* f */
  537.     { 0,    GOTO_CMD },
  538.     { 0,    GO_LF_CMD },
  539.     { 0,    UNBOUND },
  540.     { 0,    GO_DN_CMD },
  541.     { 0,    GO_UP_CMD },        /* k */
  542.     { 0,    GO_RT_CMD },
  543.     { 0,    MOVE_REG },
  544.     { 0,    GO_DNRT_CMD },
  545.     { 0,    SET_OPT_CMD },
  546.     { 0,    PRINT_REG },        /* p */
  547.     { 0,    UNBOUND },
  548.     { 0,    READ_ALL_CMD },
  549.     { 0,    SORT_REG },
  550.     { 0,    UNBOUND },
  551.     { 0,    GO_UPRT_CMD },        /* u */
  552.     { 0,    SET_VAR_CMD },
  553.     { 0,    WRITE_ALL_CMD },
  554.     { 0,    KILL_CELL },
  555.     { 0,    GO_UPLF_CMD }        /* y */
  556. };
  557. static struct key main_keys_2[] = {
  558.   { 255, ANSI_MAP }   /* CSI , 0x9b hopefully */
  559. };
  560.  
  561. struct keymap main_map[] = {
  562.     {&main_map[1], 0, 0, 1,
  563.     '\0','y',
  564.     &main_keys_1[0]},
  565.  
  566.     {0, 1, 0, 1,
  567.     '\233','\233',
  568.     &main_keys_2[0]}
  569. };
  570.  
  571. /* The meta-map, for key sequences that start with escape */
  572. /* We declare these in reverse order so we won't have to forward-reference
  573.    all the pointers. . . */
  574. static struct key meta_key_4[] = {
  575.     { 0,    USR_FMT_CMD },
  576.     { 0,    UNBOUND },
  577.     { 0,    OPEN_WIN_CMD },
  578.     { 0,    EXECUTE_MACRO },
  579.     { 0,    UNBOUND },
  580.     { 0,    UNBOUND },
  581.     { 255,    ANSI_MAP }
  582. };
  583.  
  584. static struct key meta_key_3[] = {
  585.     { 0,    CLOSE_WIN_CMD },
  586.     { 0,    UNBOUND },
  587.     { 0,    UNBOUND },
  588.     { 0,    UNBOUND },
  589.     { 0,    GOTO_WIN_CMD },
  590.     { 0,    SCAN_LF_CMD },
  591.     { 0,    UNBOUND },
  592.     { 0,    SCAN_DN_CMD },
  593.     { 0,    SCAN_UP_CMD },
  594.     { 0,    SCAN_RT_CMD },
  595. };
  596.  
  597. static struct key meta_key_2[] = {
  598.     { 0,    DIGIT_0 },
  599.     { 0,    DIGIT_1 },
  600.     { 0,    DIGIT_2 },
  601.     { 0,    DIGIT_3 },
  602.     { 0,    DIGIT_4 },
  603.     { 0,    DIGIT_5 },
  604.     { 0,    DIGIT_6 },
  605.     { 0,    DIGIT_7 },
  606.     { 0,    DIGIT_8 },
  607.     { 0,    DIGIT_9 },
  608.     { 0,    UNBOUND },
  609.     { 0,    UNBOUND },
  610.     { 0,    READ_KEY_CMD },
  611.     { 0,    UNBOUND },
  612.     { 0,    SAVE_KEY_CMD }
  613. };
  614.  
  615. static struct key meta_key_1[] = {
  616.     { 0,    START_MACRO },
  617.     { 0,    END_MACRO }
  618. };
  619.  
  620. #ifdef TEST
  621. #define DBG_ADD 1
  622. static struct key meta_key_0 =     { 0,    DEBUG_CMD };
  623. #else
  624. #define DBG_ADD 0
  625. #endif
  626.  
  627. struct keymap meta_map[] = {
  628. #ifdef TEST
  629.     {
  630.         &meta_map[DBG_ADD],    0,    0,    1,
  631.         CTRL('d'),CTRL('d'),
  632.         &meta_key_0
  633.     },
  634. #endif
  635.     {
  636.         &meta_map[1+DBG_ADD],    0,    0,    1,
  637.         '(',')',
  638.         &meta_key_1[0]
  639.     },{
  640.         &meta_map[2+DBG_ADD],    0,    0,    0,
  641.         '0','>',
  642.         &meta_key_2[0]
  643.     },{
  644.         &meta_map[3+DBG_ADD],    0,    0,    0,
  645.         'C', 'L',
  646.         &meta_key_3[0]
  647.     },{
  648.         &meta_map[4+DBG_ADD],    0,    0,    0,
  649.         'U','[',
  650.         &meta_key_4[0]
  651.     },{
  652.         &meta_map[5+DBG_ADD],    0,    0,    0,
  653.         'c', 'l',
  654.         &meta_key_3[0],
  655.     },{
  656.         0,            1,    0,    0,
  657.         'u', 'x',
  658.         &meta_key_4[0]
  659.     }
  660. };
  661.  
  662. /* For keyboards that return ^[ [ {A B C D} for the arrow keys */
  663. static struct key ansi_key[] = {
  664.     { 0,    GO_UP_CMD },
  665.     { 0,    GO_DN_CMD },
  666.     { 0,    GO_RT_CMD },
  667.     { 0,    GO_LF_CMD }
  668. };
  669.  
  670. struct keymap ansi_map = {
  671.     0,        1,    0,    1,
  672.     'A', 'D',
  673.     &ansi_key[0]
  674. };
  675. /* FOr dealing with meta-digit commands */
  676. static struct keymap digit_map = {
  677.     &main_map[0],    1,    0,    0,
  678.     '0','9',
  679.     &meta_key_2[0]
  680. };
  681.  
  682. /* The user commands that are defined in this file. . . */
  683. extern void scroll_cell_cursor EXT1(int);
  684. extern void copy_region();
  685. extern void copy_values_region();
  686. extern void set_format();
  687. extern void move_region();
  688. extern void delete_region();
  689. extern void format_area();
  690. extern void open_window();
  691. extern void close_window();
  692. extern void goto_window();
  693. extern void print_region EXT2(struct rng *, char *);
  694.  
  695. static void do_debug EXT1(char *);
  696. static void end_macro EXT0();
  697. /* static void do_ansi_cmd EXT0(); */
  698. static void do_break_cmd EXT0();
  699. static void set_default EXT0();
  700. static void quit_cmd EXT0();
  701. static void set_usr_fmt EXT1(char *);
  702. static void set_var EXT1(char *);
  703. static void show_var EXT1(char *);
  704. static void show_all_var EXT0();
  705. static void recalc_cmd EXT0();
  706. static void bind_key_cmd EXT1(char *);
  707. static void desc_key_cmd EXT0();
  708. static void read_cmds_cmd EXT1(FILE *);
  709. static void write_keys_cmd EXT1(FILE *);
  710. static void write_cmd EXT1(FILE *);
  711. static void read_cmd EXT1(FILE *);
  712. static void read_merge_cmd EXT1(FILE *);
  713. static void kill_all_cmd EXT0();
  714. static void sort_region_cmd EXT1(char *);
  715. static void write_reg_cmd EXT2(FILE *, struct rng *);
  716. static void start_macro EXT0();
  717. static void execute_cmd EXT1(char *);
  718. static void interact_macro_cmd EXT0();
  719. static void goto_region EXT1(struct rng *);
  720. static void mark_cell_cmd EXT0();
  721. static void do_input_cmd EXT2(int, int);
  722. static void format_cell_cmd EXT0();
  723. static void kill_cell_cmd EXT0();
  724. static void digit_cmd EXT1(int);
  725. static void show_options EXT0();
  726. static void bound_macro EXT1(int);
  727. static void make_keymap EXT1(char *);
  728. static void scan_cell_cursor EXT1(int);
  729. static void shift_cell_cursor EXT1(int);
  730.  
  731. /* For lines that take text input, the second letter (eg 'ta' or 'fdr')
  732.    specifies which struct line to use to contain the text generated for that
  733.    command.  That way, the command will have the appropriate defaults, etc.
  734.    Currently 'a' through 'n' are used (?).
  735.     a    set options
  736.     b    set/show variables
  737.     c    read/write keymap
  738.     d    read/write file
  739.     e    read-merge    write-region
  740.     f    copy region/copy values region
  741.     g    format-region
  742.     h    move-region
  743.     i    print-region
  744.     j    sort-region
  745.     k    delete-region
  746.     l    execute-command
  747.     m    goto-cell
  748.     n    open-window
  749.     o    close-window
  750.     p    debug
  751.     q    bind-key
  752.     r    set-user-format
  753.     s    create-keymap
  754.  */
  755.  
  756. static struct cmd_func cmd_funcs[] = {
  757. {    "unbound",        0,    ALL,    0 },
  758.  
  759. {    "go-up",        "n0",    ALL,    shift_cell_cursor },
  760. {    "go-down",        "n1",    ALL,    shift_cell_cursor },
  761. {    "go-right",        "n2",    ALL,    shift_cell_cursor },
  762. {    "go-left",        "n3",    ALL,    shift_cell_cursor },
  763. {    "go-upright",        "n4",    ALL,    shift_cell_cursor },
  764. {    "go-upleft",        "n5",    ALL,    shift_cell_cursor },
  765. {    "go-downright",        "n6",    ALL,    shift_cell_cursor },
  766. {    "go-downleft",        "n7",    ALL,    shift_cell_cursor },
  767.  
  768. {    "scroll-up",        "n0",    ALL,    scroll_cell_cursor },
  769. {    "scroll-down",        "n1",    ALL,    scroll_cell_cursor },
  770. {    "scroll-right",        "n2",    ALL,    scroll_cell_cursor },
  771. {    "scroll-left",        "n3",    ALL,    scroll_cell_cursor },
  772. {    "scroll-upright",    "n4",    ALL,    scroll_cell_cursor },
  773. {    "scroll-upleft",    "n5",    ALL,    scroll_cell_cursor },
  774. {    "scroll-downright",    "n6",    ALL,    scroll_cell_cursor },
  775. {    "scroll-downleft",    "n7",    ALL,    scroll_cell_cursor },
  776.  
  777. {    "scan-up",        "n0",    ALL,    scan_cell_cursor },
  778. {    "scan-down",        "n1",    ALL,    scan_cell_cursor },
  779. {    "scan-right",        "n2",    ALL,    scan_cell_cursor },
  780. {    "scan-left",        "n3",    ALL,    scan_cell_cursor },
  781.  
  782. {    "break",        0,    ALL|BRK,do_break_cmd },
  783. {    "recenter-window",    0,    ALL,    recenter_cur_win },
  784. {    "set-option",        "ta",    ALL,    set_options },
  785. {    "set-defaults",        "T",    ALL,    set_default },
  786. {    "quit",            "C",    ALL,    quit_cmd },
  787. {    "redraw-screen",    0,    ALL,    disp_scrn },
  788. {    "set-user-format",    "trT",    ALL,    set_usr_fmt },
  789.  
  790. /* If you change the line used by {set,show}-variable, you must change
  791.    {set,show}_var to use the correct line, else bad things will happen */
  792. {    "set-variable",        "tb",    ALL,    set_var },
  793. {    "show-variable",    "tb",    ALL,    show_var },
  794. {    "show-all-variables",    0,    ALL,    show_all_var },
  795.  
  796. {    "recalculate",        0,    ALL,    recalc_cmd },
  797. {    "bind-key",        "tqT",    ALL,    bind_key_cmd },
  798. {    "describe-key",        "T",    ALL,    desc_key_cmd },
  799. {    "read-commands",    "fcr",    ALL,    read_cmds_cmd },
  800. {    "write-keys",        "fcw",    ALL,    write_keys_cmd },
  801.  
  802. /* If you change the line used by {read,write}-file, you must change
  803.    main() to use the correct line, else chaos will erupt */
  804. {    "write-file",        "fdw",    ALL,    write_cmd },
  805. {    "read-file",        "Cfdr",    ALL,    read_cmd },
  806. {    "read-merge",        "fer",    ALL,    read_merge_cmd },
  807. {    "clear-spreadsheet",    "C",    ALL,    kill_all_cmd },
  808.  
  809. {    "copy-region",        "Rf",    ALL,    copy_region },
  810. {    "copy-values-in_region","Rf",    ALL,    copy_values_region },
  811. {    "format-region",    "rg",    ALL,    format_area },
  812. {    "move-region",        "Rh",    ALL,    move_region },
  813. {    "print-region",        "Fi",    ALL,    print_region },
  814. {    "sort-region",        "tj",    ALL,    sort_region_cmd },
  815. {    "write-region-to-file",    "Fe",    ALL,    write_reg_cmd },
  816. {    "delete-region",    "rk",    ALL,    delete_region },
  817.  
  818. {    "start-entering-macro",    0,    ALL,    start_macro },
  819. {    "execute-command",    "tl",    ALL,    execute_cmd },
  820. {    "macro-interactive-here",0,    ALL,    interact_macro_cmd },
  821.  
  822. /* If you change which line goto-cell uses, you *must* modify goto_region() */
  823. {    "goto-cell",        "rm",    ALL,    goto_region },
  824. {    "mark-cell",        0,    ALL,    mark_cell_cmd },
  825. {    "edit-cell",        "T0",    ALL|WTH_CHR,do_input_cmd },
  826. {    "edit-value-cell",    "T1",    ALL|WTH_CHR,do_input_cmd },
  827. {    "format-cell",        "T",    ALL,    format_cell_cmd },
  828. {    "delete-cell",        0,    ALL,    kill_cell_cmd },
  829. {    "edit-cell-with-default","T3",    ALL|WTH_CHR,do_input_cmd },
  830.  
  831. {    "digit-0",        "N",    ALL|NC,    digit_cmd },
  832. {    "digit-1",        "N",    ALL|NC,    digit_cmd },
  833. {    "digit-2",        "N",    ALL|NC,    digit_cmd },
  834. {    "digit-3",        "N",    ALL|NC,    digit_cmd },
  835. {    "digit-4",        "N",    ALL|NC,    digit_cmd },
  836. {    "digit-5",        "N",    ALL|NC,    digit_cmd },
  837. {    "digit-6",        "N",    ALL|NC,    digit_cmd },
  838. {    "digit-7",        "N",    ALL|NC,    digit_cmd },
  839. {    "digit-8",        "N",    ALL|NC,    digit_cmd },
  840. {    "digit-9",        "N",    ALL|NC,    digit_cmd },
  841.  
  842. {    "enter-text-in-cell",    "T2",    WTH_CHR|ALL,do_input_cmd },
  843.  
  844. {    "show-options",        0,    ALL,    show_options },
  845.  
  846. {    "open-window",        "tn",    ALL,    open_window },
  847. {    "close-window",        "to",    ALL,    close_window },
  848. {    "goto-window",        "to",    ALL,    goto_window },
  849.  
  850. {    "stop-entering-macro",    0,    ALL,    end_macro },
  851.  
  852. {    "create-keymap",    "ts",    ALL,    make_keymap },
  853.  
  854. #ifdef TEST
  855. {    "debug",        "tp",    ALL,    do_debug },
  856. #endif
  857.  
  858. {    "bound-menu",        0,    WTH_CHR|ALL,0 },
  859. {    0,            0,    0,    0 }
  860.  
  861. };
  862.  
  863.  
  864.  
  865. #ifdef __TURBOC__
  866. extern void deal_alarm EXT0();
  867.  
  868. static unsigned char
  869. real_get_chr FUN0()
  870. {
  871.     unsigned char ch;
  872.  
  873.     if(auto_recalc) {
  874.         current_cycle++;
  875.         if(!bkgrnd_recalc) {
  876.             while(eval_next_cell())
  877.                 ;
  878.         } else {
  879.             if(timer_active) {
  880.  
  881.                 static int ttick;
  882.                 int ev = 1;
  883.  
  884.                 for(;kbhit()==0;) {
  885.                     if(ev) {
  886.                         ev=eval_next_cell();
  887.                         if(!ev)
  888.                             redisp();
  889.                     }
  890.                      if(ttick++>=signal_ticks) {
  891.                         deal_alarm();
  892.                         ttick=0;
  893.                         ev=1;
  894.                     }
  895.                 }
  896.             }
  897.  
  898.             while(kbhit()==0 && eval_next_cell())
  899.                 ;
  900.         }
  901.     }
  902.     redisp();
  903.     ch=getch();
  904.     if(making_macro) {
  905.         if(ch==0)
  906.             *making_macro++=0x80|'a';
  907.         else if(ch=='{')
  908.             *making_macro++=0x80|'b';
  909.         else
  910.             *making_macro++=ch;
  911.         if(making_macro>=making_macro_start+making_macro_size) {
  912.  
  913.             making_macro_start=ck_realloc(making_macro_start,5+making_macro_size*2);
  914.             making_macro=making_macro_start+making_macro_size;
  915.             making_macro_size*=2;
  916.         }
  917.     }
  918.     return ch;
  919. }
  920.  
  921. #else
  922. #if !defined(SIGIO) || defined(AMIGA)
  923. #undef CTRL(X)
  924. #undef NC
  925. #include <curses.h>
  926.  
  927. int intr1 = 0;
  928. int intr2 = 0;
  929. static unsigned char
  930. real_get_chr FUN0()
  931. {
  932.     static int saved;
  933.     unsigned char ret;
  934.  
  935.     if(saved) {
  936.         ret=saved-1;
  937.         saved=0;
  938.         goto fini;
  939.     }
  940.     if(auto_recalc) {
  941.         current_cycle++;
  942.         if(!bkgrnd_recalc) {
  943.             while(eval_next_cell())
  944.                 ;
  945.         } else {
  946.             int ev;
  947.  
  948.             do {
  949. #if !defined(AMIGA)
  950.                 nodelay(stdscr, TRUE);
  951. #endif
  952.                 while(ev=eval_next_cell())
  953.                     if((ret=getch())!=ERR)
  954.                         goto fini;
  955. #ifdef TEST
  956.                     else
  957.                         intr1++;
  958. #endif
  959. #if !defined(AMIGA)
  960.                 nodelay(stdscr,FALSE);
  961. #endif
  962.                 redisp();
  963.                 ret=getch();
  964. #ifdef TEST
  965.                 if(ret==ERR)
  966.                     intr2++;
  967. #endif
  968.             } while(ret==ERR);
  969.             goto fini;
  970.         }
  971.     }
  972.     redisp();
  973.     ret= getch();
  974.  fini:
  975.     if(making_macro) {
  976.         if(ret==0)
  977.             *making_macro++=0x80|'a';
  978.         else if(ret=='{')
  979.             *making_macro++=0x80|'b';
  980.         else
  981.             *making_macro++=ret;
  982.         if(making_macro>=making_macro_start+making_macro_size) {
  983.  
  984.             making_macro_start=ck_realloc(making_macro_start,5+making_macro_size*2);
  985.             making_macro=making_macro_start+making_macro_size;
  986.             making_macro_size*=2;
  987.         }
  988.     }
  989.     if(ret&0x80) {
  990.       if(ret==0x9b)
  991.         {
  992. /* this is a test pass travis */
  993.           return 0x9b;
  994.         }
  995.  
  996.       saved=1+(ret&0x7f);
  997.       return CTRL('[');
  998.     }
  999.     return ret;
  1000. }
  1001. #else
  1002.  
  1003. #ifdef __STDC__
  1004. volatile
  1005. #endif
  1006. int have_kbd_input = 0;
  1007.  
  1008. static char ibuf[100];
  1009. static int i_in,i_cnt;
  1010.  
  1011. static unsigned char
  1012. real_get_chr FUN0()
  1013. {
  1014.     unsigned char ch;
  1015.     static int save;
  1016.  
  1017.     if(save) {
  1018.         ch=save-1;
  1019.         save=0;
  1020.         goto fini;
  1021.     }
  1022.     if(i_cnt) {
  1023.         ch=ibuf[i_cnt++];
  1024.         if(i_cnt==i_in)
  1025.             i_cnt=i_in=0;
  1026.         goto fini;
  1027.     }
  1028.     for(;;) {
  1029.         if(auto_recalc) {
  1030.             current_cycle++;
  1031.             if(bkgrnd_recalc) {
  1032.                 while(!have_kbd_input && eval_next_cell())
  1033.                     ;
  1034.             } else {
  1035.                 while(eval_next_cell())
  1036.                     ;
  1037.             }
  1038.         }
  1039.         redisp();
  1040.         if(have_kbd_input) {
  1041.             int ret;
  1042.  
  1043.             ret=read(0,ibuf,sizeof(ibuf));
  1044.             if(ret==1) {
  1045.                 have_kbd_input=0;
  1046.                 ch=ibuf[0];
  1047.                 goto fini;
  1048.             }
  1049.             if(ret>1) {
  1050.                 if(have_kbd_input<=ret)
  1051.                     have_kbd_input=0;
  1052.                 else
  1053.                     have_kbd_input-=ret;
  1054.                 i_cnt=1;
  1055.                 i_in=ret;
  1056.                 ch=ibuf[0];
  1057.                 goto fini;
  1058.             }
  1059.             if(ret==0 || (errno!=EWOULDBLOCK && errno!=EINTR))
  1060.                 return EOF;
  1061.         }
  1062.         pause();
  1063.     }
  1064.  fini:
  1065.     if(making_macro) {
  1066.         if(ch==0)
  1067.             *making_macro++=0x80|'a';
  1068.         else if(ch=='{')
  1069.             *making_macro++=0x80|'b';
  1070.         else
  1071.             *making_macro++=ch;
  1072.         if(making_macro>=making_macro_start+making_macro_size) {
  1073.  
  1074.             making_macro_start=ck_realloc(making_macro_start,5+making_macro_size*2);
  1075.             making_macro=making_macro_start+making_macro_size;
  1076.             making_macro_size*=2;
  1077.         }
  1078.     }
  1079.     if(ch&0x80) {
  1080.         save=1+(ch&0x7f);
  1081.         ch=CTRL('[');
  1082.     }
  1083.     return ch;
  1084. }
  1085.  
  1086. void
  1087. got_sigio FUN1(int,sig)
  1088. {
  1089.     have_kbd_input++;
  1090. }
  1091.  
  1092. #endif
  1093. #endif
  1094.  
  1095. #ifdef TEST
  1096. extern int yydebug;
  1097.  
  1098. int debug;
  1099. int dbg_do_stderr;
  1100.  
  1101. extern void dbg_print_ref_fm();
  1102.  
  1103. static void
  1104. dbg_show_var FUN2(char *,name, struct var *,v)
  1105. {
  1106.     char *ptr;
  1107.  
  1108.     /* if(*cmd && strncmp(cmd,v->var_name,strlen(cmd)))
  1109.         continue; */
  1110.     if(v->var_flags==VAR_UNDEF)
  1111.         ptr="Undefined";
  1112.     else if(v->var_flags==VAR_CELL)
  1113.         ptr="Cell";
  1114.     else if(v->var_flags==VAR_RANGE)
  1115.         ptr="Range";
  1116.     else
  1117.         ptr="*UNKNOWN*";
  1118.  
  1119.     text_line("%s %s %s  ",v->var_name,ptr,range_name(&(v->v_rng)));
  1120.     if(!v->var_ref_fm)
  1121.         text_line("no refs");
  1122.     else
  1123.         dbg_print_ref_fm(v->var_ref_fm);
  1124. }
  1125. /* Debugging is very important.  That's why there is an entire function to
  1126.    handle it. . .  :-)
  1127.  */
  1128. static void
  1129. do_debug FUN1(char *,cmd)
  1130. {
  1131.     CELL *cp;
  1132.     char *ptr;
  1133.     FILE *output;
  1134.     extern struct ref_fm *timer_cells;
  1135.     extern struct rng all_rng;
  1136.  
  1137.     extern void dbg_print_ref_to();
  1138.     extern void dbg_print_formula();
  1139.     extern void dbg_print_cell EXT1(CELL *);
  1140.     extern void dbg_print_cols EXT1(CELLREF);
  1141.     extern void dbg_print_rows EXT0();
  1142.  
  1143.     extern void dbg_print_array EXT0();
  1144.     extern void ref_stats EXT0();
  1145.  
  1146.     extern int fputs();
  1147.     extern void text_start();
  1148.     extern void text_finish();
  1149.  
  1150.     output=stdout;
  1151.     ptr=cmd;
  1152.     switch(*ptr++) {
  1153.     case 'd':
  1154.         debug=astol(&ptr);
  1155.         info_msg("Debug now %d",debug);
  1156.         return;
  1157.  
  1158.     case 'f':
  1159.         while(*ptr==' ')
  1160.             ptr++;
  1161.         freopen(ptr,"w",stderr);
  1162.         dbg_do_stderr=0;
  1163.         return;
  1164.  
  1165.     case 'y':
  1166.         yydebug= !yydebug;
  1167.         return;
  1168.  
  1169.     case 'E':
  1170.         output=stderr;
  1171.         break;
  1172.  
  1173.     default:
  1174.         break;
  1175.     }
  1176.  
  1177.     --ptr;
  1178.     text_start();
  1179.     switch(*ptr++) {
  1180.         CELLREF rr,cc;
  1181.         int n;
  1182.         int todo;
  1183.         struct rng rn;
  1184.     default:
  1185.         print_buf[0]='\0';
  1186.         break;
  1187.  
  1188.     case 'R':
  1189.         dbg_print_rows();
  1190.         break;
  1191.  
  1192.     case 'C':
  1193.         n=astol(&ptr);
  1194.         dbg_print_cols(n);
  1195.         break;
  1196.  
  1197.     case 'p':
  1198.         dbg_print_array();
  1199.         break;
  1200.  
  1201.     case 'S':
  1202.         ref_stats();
  1203.         break;
  1204.  
  1205.     case 'r':
  1206.         todo= *ptr++;
  1207.         if(!*ptr)
  1208.             find_cells_in_range(&all_rng);
  1209.         else {
  1210.             get_abs_rng(&ptr,&rn);
  1211.             find_cells_in_range(&rn);
  1212.         }
  1213.         ptr=print_buf;
  1214.         while(cp=next_row_col_in_range(&rr,&cc)) {
  1215.             text_line("(r%uc%u)",rr,cc);
  1216.             if(todo=='f' && cp->cell_refs_from) {
  1217.                 dbg_print_ref_fm(cp->cell_refs_from);
  1218.             } else if(todo=='t' && cp->cell_refs_to) {
  1219.                 dbg_print_ref_to(cp->cell_refs_to,cp->cell_formula);
  1220.             } else if(todo=='c') {
  1221.                 dbg_print_cell(cp);
  1222.             } else if(todo=='e' && cp->cell_formula) {
  1223.                 dbg_print_formula(cp);
  1224.             } else if(todo=='F') {
  1225.                 text_line("flags %#x  cycle %d",cp->cell_flags,cp->cell_cycle);
  1226.             }
  1227.         }
  1228.         break;
  1229.  
  1230.     case 't':
  1231. #ifdef hp800
  1232.     {
  1233.         sigset_t sigs;
  1234.  
  1235.         sigprocmask(0,(void *)0,&sigs);
  1236.         text_line("Timer is %sactive, ticks=%lu (%lu), sigs %x.%x.%x.%x.%x.%x.%x.%x",timer_active ? "" : "not ",signal_ticks,signal_ticks/TIMER_MULT,sigs.sigset[0],sigs.sigset[1],sigs.sigset[2],sigs.sigset[3],sigs.sigset[4],sigs.sigset[5],sigs.sigset[6],sigs.sigset[7]);
  1237.         dbg_print_ref_fm(timer_cells);
  1238.     }
  1239. #else
  1240.         text_line("Timer is %sactive, ticks=%lu (%lu)",timer_active ? "" : "not ",signal_ticks,signal_ticks/TIMER_MULT);
  1241.         dbg_print_ref_fm(timer_cells);
  1242. #endif
  1243.         break;
  1244.  
  1245.     case 'v':
  1246.         while(*ptr==' ')
  1247.             ptr++;
  1248.         cmd=ptr;
  1249.         for_all_vars(dbg_show_var);
  1250.         break;
  1251.  
  1252.     case 'm':
  1253.         if(*ptr)
  1254.             desc_map(the_maps[atoi(ptr)]);
  1255.         break;
  1256.  
  1257.     case 'w':
  1258.         dbg_show_wins();
  1259.         break;
  1260. #if defined(SIGIO) && !defined(AMIGA)
  1261.     case 'k':
  1262.         text_line("i_in %d  i_cnt %d  have_input %d",i_in,i_cnt,have_kbd_input);
  1263.         break;
  1264. #endif
  1265.     }
  1266.     text_finish();
  1267. }
  1268.  
  1269. #endif
  1270.  
  1271. void
  1272. init_maps FUN0()
  1273. {
  1274.     static char main_name[] = "main";
  1275.     static char meta_name[] = "meta";
  1276.     static char edit_name[] = "edit";
  1277.     static char em_name[] = "edit-meta";
  1278.     static char ansi_name[] = "ansi";
  1279.     static char digit_name[] = "digit";
  1280.  
  1281.     extern struct keymap edit_map[];
  1282.     extern struct keymap edit_meta_map[];
  1283.  
  1284.     extern struct cmd_func edit_funcs[];
  1285.  
  1286.     the_maps=ck_malloc(sizeof(struct keymap *)*6);
  1287.     map_names=ck_malloc(sizeof(char *)*6);
  1288.     num_maps=6;
  1289.     the_maps[0]= &main_map[0];
  1290.     the_maps[1]= &meta_map[0];
  1291.     the_maps[2]= &edit_map[0];
  1292.     the_maps[3]= &edit_meta_map[0];
  1293.     the_maps[4]= &ansi_map;
  1294.     the_maps[5]= &digit_map;
  1295.     map_names[0]=main_name;
  1296.     map_names[1]=meta_name;
  1297.     map_names[2]=edit_name;
  1298.     map_names[3]=em_name;
  1299.     map_names[4]=ansi_name;
  1300.     map_names[5]=digit_name;
  1301.     the_funcs=ck_malloc(sizeof(struct cmd_func *)*2);
  1302.     num_funcs=2;
  1303.     the_funcs[0]= &cmd_funcs[0];
  1304.     the_funcs[1]= &edit_funcs[0];
  1305. }
  1306. static int add_usr_cmds FUN1(struct cmd_func *, new_cmds)
  1307. {
  1308.     num_funcs++;
  1309.  
  1310.     the_funcs=ck_realloc(the_funcs,num_funcs*sizeof(struct cmd_func *));
  1311.     the_funcs[num_funcs-1]=new_cmds;
  1312.     return num_funcs-1;
  1313. }
  1314. #ifdef USE_DLD
  1315. static int add_usr_maps FUN1(struct keymap **, new_maps)
  1316. {
  1317.     int n;
  1318.  
  1319.     for(n=1;new_maps[n];n++)
  1320.         ;
  1321.  
  1322.     the_maps=ck_realloc(the_maps,(n+num_maps)*sizeof(struct keymap *));
  1323.     bcopy(new_maps, &the_maps[num_maps],n*sizeof(struct keymap *));
  1324.     num_maps+=n;
  1325.     return num_maps-n;
  1326. }
  1327. #endif
  1328.  
  1329. int
  1330. main FUN2(int,argc, char **,argv)
  1331. {
  1332.     int c;
  1333.     int num;
  1334.     void got_sig();
  1335.  
  1336.     myname=argv[0];
  1337.  
  1338.     __make_backups=1;
  1339. #if !defined(__TURBOC__) && !defined(SYSV)
  1340.     setbuffer(stdout,buf,sizeof(buf));
  1341. #endif
  1342.     if(argc<2 || strcmp(argv[1],"-q")) {
  1343.         if(!getenv("OLEO")) {
  1344.             fprintf(stdout,"Oleo version 0.03.2, Copyright (C) 1990 Free Software Foundation, Inc.\n");
  1345.             fprintf(stdout,"There is ABSOLUTELY NO WARRANTY for Oleo; see the file COPYING\n");
  1346.             fprintf(stdout,"for details.  Oleo is free software and you are welcome to distribute\n");
  1347.             fprintf(stdout,"copies of it under certain conditions; see the file COPYING to see the\n");
  1348.             fprintf(stdout,"conditions.\n\n");
  1349.             fflush(stdout);
  1350.             sleep(5);
  1351.         }
  1352.      } else {
  1353.         --argc;
  1354.         ++argv;
  1355.     }
  1356.     init_mem();
  1357.     init_eval();
  1358.     init_refs();
  1359.     init_cells();
  1360.     init_maps();
  1361.     obstack_init(¯o_stack);
  1362.  
  1363.     c=0;
  1364.     if(argc>2 && !strcmp(argv[1],"-f")) {
  1365.          --argc;
  1366.         ++argv;
  1367.         c++;
  1368.     }
  1369.     open_display(c);
  1370.  
  1371.     if(argc>2) {
  1372.         fprintf(stderr,"Usage: %s [filename]\n",argv[0]);
  1373.         exit(1);
  1374.     }
  1375. #ifdef USE_DLD
  1376.     if(!index(myname,'/')) {
  1377.         char *name;
  1378.  
  1379.         name=dld_find_executable(myname);
  1380.         num=dld_init(name);
  1381.         free(name);
  1382.     } else
  1383.         num=dld_init(myname);
  1384.     if(num)
  1385.         error_msg("dld_init() failed: %s",(dld_errno < 0 || dld_errno > dld_nerr) ? "Unknown error" : dld_errlst[dld_errno]);
  1386.     dld_search_path=":/usr/local/lib/oleo:/lib:/usr/lib:/usr/local/lib";
  1387. #endif
  1388.  
  1389.  
  1390.     {
  1391.         FILE *fp;
  1392.         extern int fclose();
  1393.         char *ptr,*home;
  1394.         /* would be nice to use ck_fopen, but these files might not
  1395.            exist. . . */
  1396.  
  1397.         home=getenv("HOME");
  1398.         if(home) {
  1399.             ptr=mk_sprintf("%s/%s",home,RCFILE);
  1400.             if(fp=fopen(ptr,"r")) {
  1401.                 read_cmds_cmd(fp);
  1402.                 fclose(fp);
  1403.             }
  1404.             free(ptr);
  1405.         }
  1406.  
  1407.         if(fp=fopen(RCFILE,"r")) {
  1408.             read_cmds_cmd(fp);
  1409.             fclose(fp);
  1410.         }
  1411.         if(argc==2) {
  1412.             set_line(&in_line[3],argv[1]);
  1413.             if(fp=fopen(argv[1],"r")) {
  1414.                 (*read_file)(fp,0);
  1415.                 fclose(fp);
  1416.             } else
  1417.                 error_msg("Can't open %s: %s",argv[1],err_msg());
  1418.         }
  1419.     }
  1420.  
  1421.     signal(SIGINT,got_sigint);
  1422. #ifdef SIGQUIT
  1423.     signal(SIGQUIT,got_sig);
  1424.     signal(SIGILL,got_sig);
  1425.     signal(SIGEMT,got_sig);
  1426.     signal(SIGBUS,got_sig);
  1427.     signal(SIGSEGV,got_sig);
  1428.     signal(SIGPIPE,got_sig);
  1429. #endif
  1430. #if  defined(SIGIO) && !defined(AMIGA)
  1431.     signal(SIGIO,got_sigio);
  1432.     /* close(0);
  1433.     if(open("/dev/tty",0)!=0) {
  1434.         fprintf(stderr,"Didn't get 0 when trying to re-open stdin\n");
  1435.         exit(1);
  1436.     } */
  1437. #ifdef FASYNC
  1438.     term_flag=fcntl(0,F_GETFL,FASYNC /* |FNDELAY */);
  1439.     c=fcntl(0,F_SETFL,FASYNC /* |FNDELAY */);
  1440.     if(c==-1) {
  1441.         fprintf(stderr,"Can't turn on FASYNC|FNDELAY on stdin: %s\n",err_msg());
  1442.         exit(1);
  1443.     }
  1444. #else
  1445. #ifdef FIOSSAIOSTAT
  1446.     {
  1447.         int i;
  1448.  
  1449.         ioctl(0,FIOGSAIOSTAT,&i);
  1450.         term_flag=i;
  1451.         ioctl(0,FIOGNBIO, &i);
  1452.         if(i)
  1453.             term_flag+=2;
  1454.         i=1;
  1455.         ioctl(0,FIOSSAIOSTAT,&i);
  1456.         /* ioctl(0,FIOSNBIO,&i); */
  1457.         i=getpid();
  1458.         ioctl(0,FIOSSAIOOWN,&i);
  1459.     }
  1460. #endif
  1461. #endif
  1462. #endif
  1463.     recenter_cur_win();
  1464.  
  1465.     for(;;) {
  1466.         if(how_many!=1) {
  1467.             how_many=1;
  1468.             cur_status();
  1469.         }
  1470.         clear_top_before();
  1471.         map_chr(MAIN_MAP);
  1472.  
  1473.         if(topclear && !rmac)
  1474.             clear_top_after();
  1475.  
  1476.     swtch:
  1477.         if(!cur_cmd) {
  1478.             error_msg("That key is unbound");
  1479.             continue;
  1480.         }
  1481.         if((cur_cmd->func_flags&NONTOP)==0) {
  1482.             error_msg("Command '%s' is not appropriate now.",cur_cmd->func_name);
  1483.             continue;
  1484.         }
  1485.         num=global_cmd(MAIN_MAP);
  1486.         if(num==-2)
  1487.             error_msg("Command '%s' is *not* appropriate now.",cur_cmd->func_name);
  1488.         else if(num>=0) {
  1489.             c=num;
  1490.             goto swtch;
  1491.         }
  1492.     }
  1493. }
  1494.  
  1495. static FILE *
  1496. open_file FUN3(char *,prompt, struct line *,line, char *,mode)
  1497. {
  1498.     FILE *fp;
  1499.  
  1500.     if(get_inp_line(prompt,line))
  1501.         return 0;
  1502.     if((fp=xopen_with_backup(line->buf,mode))==0) {
  1503.         error_msg("Can't open file '%s':%s",line->buf,err_msg());
  1504.         return 0;
  1505.     }
  1506.     return fp;
  1507. }
  1508.  
  1509. static void
  1510. close_file FUN2(struct line *,line, FILE *,fp)
  1511. {
  1512.     int num;
  1513.  
  1514.     if(num=xclose(fp))
  1515.         error_msg("Can't close '%s': Error code %d: %s",line->buf,num,err_msg());
  1516. }
  1517.  
  1518. /* Deal with point-n-shoot */
  1519. static int
  1520. get_a_range FUN3(char *,whatfor, struct rng *,r, struct line *,line)
  1521. {
  1522.     char *ptr;
  1523.  
  1524.     if(mkrow!=NON_ROW) {
  1525.         /* The range has already been selected */
  1526.     got_rng:
  1527.         set_rng(r,mkrow,mkcol,curow,cucol);
  1528.         mkrow=NON_ROW;
  1529.         return 0;
  1530.     }
  1531.     switch(get_inp_line(whatfor,line)) {
  1532.     case 0:
  1533.         if(mkrow!=NON_ROW)
  1534.             goto got_rng;
  1535.         ptr=line->buf;
  1536.         if(get_abs_rng(&ptr,r) || *ptr!='\0') {
  1537.             error_msg("Can't parse '%s'",line->buf);
  1538.             return 1;
  1539.         }
  1540.         return 0;
  1541.     case 1:
  1542.         if(mkrow!=NON_ROW)
  1543.             goto got_rng;
  1544.         return 1;
  1545.     case 2:
  1546.         return 1;
  1547. #ifdef TEST
  1548.     default:
  1549.         panic("Get_inp_line() what?");
  1550. #endif
  1551.     }
  1552.     return 1;
  1553. }
  1554.  
  1555. static FILE *
  1556. get_range_and_file FUN3(char *,whatfor, struct rng *,r, struct line *,line)
  1557. {
  1558.     char *ptr;
  1559.     char *prompt;
  1560.     int got_rng = 0;
  1561.     FILE *ret;
  1562.     extern char *strdup();
  1563.  
  1564.     if(mkrow!=NON_ROW) {
  1565.         /* We've got the range, just get the file */
  1566.         set_rng(r,mkrow,mkcol,curow,cucol);
  1567.         got_rng++;
  1568.         mkrow=NON_ROW;
  1569.         prompt=mk_sprintf("%s %s to file",whatfor,range_name(r));
  1570.     } else
  1571.         prompt=strdup(whatfor);
  1572.  
  1573.     if(get_inp_line(prompt,line)) {
  1574.         free(prompt);
  1575.         return 0;
  1576.     }
  1577.     free(prompt);
  1578.  
  1579.     if(mkrow!=NON_ROW) {
  1580.         if(got_rng) {
  1581.             error_msg("Two ranges?");
  1582.             return 0;
  1583.         }
  1584.         set_rng(r,mkrow,mkcol,curow,cucol);
  1585.         mkrow=NON_ROW;
  1586.         got_rng++;
  1587.     }
  1588.     ptr=line->buf;
  1589.     if(!got_rng) {
  1590.         if(get_abs_rng(&ptr,r)) {
  1591.             error_msg("Can't parse '%s'",line->buf);
  1592.             return 0;
  1593.         }
  1594.         if(*ptr==',')
  1595.             ptr++;
  1596.     }
  1597.     while(*ptr==' ')
  1598.         ptr++;
  1599.     if(!*ptr)
  1600.         return 0;
  1601.     ret=xopen_with_backup(ptr,"w");
  1602.     if(!ret)
  1603.         error_msg("Can't open file '%s':%s",ptr,err_msg());
  1604.     return ret;
  1605. }
  1606.  
  1607. static int
  1608. get_two_ranges FUN4(char *,whatfor, struct rng *,one, struct rng *,two, struct line *,line)
  1609. {
  1610.     char *ptr;
  1611.     char *prompt;
  1612.     int num_got = 0;
  1613.     int n;
  1614.  
  1615.     prompt=0;
  1616.     if(mkrow!=NON_ROW) {
  1617.         /* We've got the first one already */
  1618.         set_rng(one,mkrow,mkcol,curow,cucol);
  1619.         mkrow=NON_ROW;
  1620.         num_got++;
  1621.     }
  1622.  
  1623.     while(num_got!=2) {
  1624.         prompt = (num_got==1) ? mk_sprintf("%s %s to",whatfor,range_name(one)) : whatfor;
  1625.         n=get_inp_line(prompt,line);
  1626.         if(prompt!=whatfor)
  1627.             free(prompt);
  1628.  
  1629.         if(n>1 || (n==1 && mkrow==NON_ROW))
  1630.             return 1;
  1631.  
  1632.         if(mkrow!=NON_ROW) {
  1633.             if(line->buf[0]) {
  1634.                 error_msg(num_got ? "Extra characters '%s'" : "'%s' is ambiguous", line->buf);
  1635.                 return 1;
  1636.             }
  1637.             set_rng(num_got ? two : one, mkrow,mkcol,curow,cucol);
  1638.             mkrow=NON_ROW;
  1639.  
  1640.             num_got++;
  1641.         } else {
  1642.             ptr=line->buf;
  1643.             if(!num_got) {
  1644.                 if(get_abs_rng(&ptr,one)) {
  1645.                     error_msg("Can't parse first range in '%s'",line->buf);
  1646.                     return 1;
  1647.                 }
  1648.                 if(*ptr==',')
  1649.                     ptr++;
  1650.             }
  1651.  
  1652.             if(get_abs_rng(&ptr,two)) {
  1653.                 if(num_got) {
  1654.                     error_msg("Can't find second range in '%s'",line->buf);
  1655.                     return 1;
  1656.                 }
  1657.                 num_got++;
  1658.             } else if(!num_got)
  1659.                 num_got+=2;
  1660.             else
  1661.                 num_got++;
  1662.         }
  1663.     }
  1664.     if(*ptr) {
  1665.         error_msg("Extra characters in '%s'",line->buf);
  1666.         return 1;
  1667.     }
  1668.  
  1669.     sprint_line(line,"%s %s",range_name(one),range_name(two));
  1670.     return 0;
  1671. }
  1672.  
  1673. /* Read a character.  If we're in a macro, read from the macro. . . */
  1674. int
  1675. get_chr FUN0()
  1676. {
  1677.     unsigned int ch;
  1678.  
  1679. #ifdef TEST
  1680.     extern CELL *my_cell;
  1681.  
  1682.     if(my_cell)
  1683.         error_msg("Something didn't clear my_cell!");
  1684. #endif
  1685.     if(rmac) {
  1686.         ch= *(rmac->mac_exe++);
  1687.         switch(ch) {
  1688.         case '{':    /* What else can we do? */
  1689.         case '\0':
  1690.             --(rmac->mac_exe);
  1691.             break;
  1692.  
  1693.         case (0x80|'a'):
  1694.             ch=0;
  1695.             break;
  1696.  
  1697.         case (0x80|'b'):
  1698.             ch='{';
  1699.             break;
  1700.         default:
  1701.             break;
  1702.         }
  1703.     } else
  1704.         ch=real_get_chr();
  1705.     return ch;
  1706. }
  1707.  
  1708. void
  1709.   map_chr FUN1(int, map)
  1710. {
  1711.   unsigned int ch;
  1712.   struct keymap *keymap;
  1713.   struct key *key;
  1714. #ifdef TEST
  1715.   extern CELL *my_cell;
  1716.   
  1717.   if(my_cell)
  1718.     error_msg("Something didn't clear my_cell!");
  1719. #endif
  1720.   keymap= the_maps[map];
  1721.   for(;;) {
  1722.     /* ch=get_chr(); */
  1723.     if(rmac) {
  1724.       int len;
  1725.       unsigned char *ptr;
  1726.       
  1727.     tryagain:
  1728.       ch= *(rmac->mac_exe++);
  1729.       switch(ch) {
  1730.       case '\0':
  1731.     cur_vector=0;
  1732.     cur_cmd= &cmd_funcs[END_MACRO];
  1733.     cur_chr=0;
  1734.     return;
  1735.     
  1736.       case 0x80|'a':
  1737.     ch='\0';
  1738.     break;
  1739.     
  1740.       case 0x80|'b':
  1741.     ch='{';
  1742.     break;
  1743.     
  1744.       case '{':
  1745.     for(ptr=rmac->mac_exe;*ptr && *ptr!=' ' && *ptr!='}';ptr++)
  1746.       ;
  1747.     len=ptr-rmac->mac_exe;
  1748.     for(cur_vector=0;cur_vector<num_funcs;cur_vector++)
  1749.       for(cur_cmd= &the_funcs[cur_vector][0];cur_cmd->func_name;cur_cmd++)
  1750.         if(!strincmp((char *)(rmac->mac_exe),cur_cmd->func_name,len) && cur_cmd->func_name[len]=='\0') {
  1751.           cur_chr='\0';
  1752.           goto out;
  1753.         }
  1754.     error_msg("Ignoring unknown function '%.*s' in macro",len,rmac->mac_exe);
  1755.     while(*ptr!='\0' && *ptr!='}')
  1756.       ptr++;
  1757.     if(*ptr=='}')
  1758.       ptr++;
  1759.     rmac->mac_exe=ptr;
  1760.     goto tryagain;
  1761.     
  1762.       out:
  1763.     if(*ptr==' ') {
  1764.       /* ... add argument support here ... */
  1765.       if(!cur_cmd->func_args) {
  1766.         error_msg("Ignoring extra operand to %s",cur_cmd->func_name);
  1767.         while(*ptr && *ptr!='}')
  1768.           ptr++;
  1769.         if(*ptr=='}')
  1770.           ptr++;
  1771.       } else if(cur_cmd->func_args[0]=='n') {
  1772.         how_many=astol((char **)(&ptr));
  1773.         if(*ptr=='}')
  1774.           ptr++;
  1775.       } else {
  1776.         macro_func_arg=(char *)ptr;
  1777.         while(*ptr && *ptr!='}')
  1778.           ptr++;
  1779.         if(*ptr=='}')
  1780.           *ptr++='\0';
  1781.       }
  1782.       rmac->mac_exe=ptr;
  1783.     } else
  1784.       rmac->mac_exe+=len+1;
  1785.     return;
  1786.       }
  1787.     } else
  1788.       ch=real_get_chr();
  1789.     for(;;) {
  1790.       if(ch>=keymap->lochr && ch<=keymap->hichr) {
  1791.     key= keymap->map_dense ? keymap->keys : &(keymap->keys[ch-keymap->lochr]);
  1792.     if(key->vector==255) {
  1793.       keymap=the_maps[key->code];
  1794.       break;
  1795.     }
  1796.     if(key->vector!=0 || key->code!=0) {
  1797.       cur_vector=key->vector;
  1798.       cur_cmd= &(the_funcs[key->vector][key->code]);
  1799.       cur_chr=ch;
  1800.       return;
  1801.     }
  1802.       }
  1803.       if (!(keymap=keymap->map_next)) {
  1804.     /* Searched through all the keymaps, and didn't find a match */
  1805.     cur_vector=0;
  1806.     cur_cmd=0;
  1807.     cur_chr=ch;
  1808.     return;
  1809.       }
  1810.     }
  1811.   }
  1812. }
  1813.  
  1814. /* Return values:
  1815.     -3    break key!
  1816.     -2    c is inappropriate
  1817.     -1    C is OK
  1818.     0+    New char value is ret-1;
  1819.  */
  1820.  
  1821. int
  1822. global_cmd FUN1(int,magic)
  1823. {
  1824.     char *ptr;
  1825.     struct rng fm,to;
  1826.     FILE *fp;
  1827.     static struct line confirm;
  1828.     struct cmd_func *cmd;
  1829.  
  1830.     if(!cur_cmd)
  1831.         return -2;
  1832.     cmd=cur_cmd;
  1833.     if(cmd->func_args) {
  1834.         ptr=cmd->func_args;
  1835.  
  1836.     next_arg:
  1837.         switch(*ptr++) {
  1838.         case 'R':
  1839.             if(get_two_ranges(cmd->func_name,&fm,&to,&in_line[*ptr++-'a']))
  1840.                 break;
  1841.             (*cmd->func_func)(&fm,&to);
  1842.             break;
  1843.  
  1844.         case 'r':
  1845.             if(get_a_range(cmd->func_name,&to,&in_line[*ptr++-'a']))
  1846.                 break;
  1847.             (*cmd->func_func)(&to);
  1848.             break;
  1849.  
  1850.         case 't':
  1851.             if(get_inp_line(cmd->func_name,&in_line[*ptr++-'a']))
  1852.                 break;
  1853.             (*cmd->func_func)(in_line[cmd->func_args[1]-'a'].buf);
  1854.             break;
  1855.  
  1856.         case 'C':
  1857.             if(modified==0)
  1858.                 goto next_arg;
  1859.             set_line(&confirm,0);
  1860.             if(   get_inp_line("Are you SURE",&confirm)
  1861.                || (confirm.buf[0]!='Y' && confirm.buf[0]!='y'))
  1862.                 return -1;
  1863.             goto next_arg;
  1864.  
  1865.         case 'f':
  1866.             fp=open_file(cmd->func_name,&in_line[*ptr-'a'],ptr+1);
  1867.             if(!fp)
  1868.                 break;
  1869.             (*cmd->func_func)(fp);
  1870.             close_file(&in_line[*ptr++-'a'],fp);
  1871.             break;
  1872.  
  1873.         case 'F':
  1874.             fp=get_range_and_file(cmd->func_name,&to,&in_line[*ptr-'a']);
  1875.             if(!fp)
  1876.                 break;
  1877.             (*cmd->func_func)(fp,&to);
  1878.             close_file(&in_line[*ptr++-'a'],fp);
  1879.             break;
  1880.  
  1881.         case 'n':
  1882.             if(!*ptr)
  1883.                 (*cmd->func_func)();
  1884.             else if(*ptr>='0' && *ptr<='9')
  1885.                 (*cmd->func_func)(*ptr-'0');
  1886.             else if(*ptr>='a' && *ptr<='z')
  1887.                 (*cmd->func_func)((*ptr-'a')*26+ptr[1]-'a');
  1888.             else
  1889.                 (*cmd->func_func)();
  1890.             break;
  1891.  
  1892.         case 'T':
  1893.             if(*ptr>='0' && *ptr<='9')
  1894.                 (*cmd->func_func)(*ptr-'0',cur_chr);
  1895.             else
  1896.                 (*cmd->func_func)();
  1897.             break;
  1898.  
  1899.         case 'N':
  1900.             (*cmd->func_func)(magic);
  1901.             return cur_chr;
  1902.  
  1903.         case '\0':
  1904.             (*cmd->func_func)();
  1905.             break;
  1906.  
  1907. #ifdef TEST
  1908.         default:
  1909.             panic("Unknown arg type %s in global_cmd",ptr);
  1910. #endif
  1911.         }
  1912.         if(cmd->func_flags&BRK)
  1913.             return -3;
  1914.         return -1;
  1915.     } else if(cmd->func_func) {
  1916.         if(cmd->func_flags&WTH_CHR)
  1917.             (*cmd->func_func)(cur_chr);
  1918.         else
  1919.             (*cmd->func_func)();
  1920.         if(cmd->func_flags&BRK)
  1921.             return -3;
  1922.         return -1;
  1923.     }
  1924.     return -2;
  1925. }
  1926.  
  1927. static void
  1928. write_keys_cmd FUN1(FILE *,fp)
  1929. {
  1930.     struct keymap *map;
  1931.     int n;
  1932.     int key;
  1933.     int vec;
  1934.     int code;
  1935.  
  1936.     for(n=0;n<num_maps;n++) {
  1937.         char *def;
  1938.  
  1939.         for(map=the_maps[n];map && !map->map_end;map=map->map_next)
  1940.             ;
  1941.         def=0;
  1942.         if(map && map->map_next) {
  1943.             for(key=0;key<num_maps;key++)
  1944.                 if(the_maps[key]==map->map_next) {
  1945.                     def=map_names[key];
  1946.                     break;
  1947.                 }
  1948.         }
  1949.         if(def)
  1950.             fprintf(fp,"create-keymap %s %s\n",map_names[n],def);
  1951.         else
  1952.             fprintf(fp,"create-keymap %s\n",map_names[n]);
  1953.     }
  1954.     for(n=0;n<num_maps;n++) {
  1955.         for(map=the_maps[n];map;map=map->map_next) {
  1956.             for(key=map->lochr;key<=map->hichr;key++) {
  1957.                 if(map->map_dense) {
  1958.                     vec=map->keys[0].vector;
  1959.                     code=map->keys[0].code;
  1960.                 } else {
  1961.                     vec=map->keys[key-map->lochr].vector;
  1962.                     code=map->keys[key-map->lochr].code;
  1963.                 }
  1964.                 if(vec==255)
  1965.                     fprintf(fp,"bind-key %s %s %s\n",
  1966.                         map_names[n],
  1967.                         map_names[code],
  1968.                         char_to_string(key));
  1969.                 else if(vec || code)
  1970.                     fprintf(fp,"bind-key %s %s %s\n",
  1971.                         map_names[n],
  1972.                         the_funcs[vec][code].func_name,
  1973.                         char_to_string(key));
  1974.             }
  1975.             if(map->map_end)
  1976.                 map=0;
  1977.         }
  1978.     }
  1979. }
  1980.  
  1981. static void
  1982. clear_keymap FUN1(struct keymap *,m)
  1983. {
  1984.     int n;
  1985.  
  1986.     while(m) {
  1987.         if(m->map_malloc) {
  1988.             if(m->map_dense) {
  1989.                 m->keys[0].vector=0;
  1990.                 m->keys[0].code=0;
  1991.                 m->hichr=m->lochr;
  1992.             } else {
  1993.                 for(n=0;n<=m->hichr-m->lochr;n++) {
  1994.                     m->keys[n].vector=0;
  1995.                     m->keys[n].code=0;
  1996.                 }
  1997.             }
  1998.         } else {
  1999.             m->keys=ck_malloc(sizeof(struct key)*(1+m->hichr-m->lochr));
  2000.             for(n=0;n<=m->hichr-m->lochr;n++) {
  2001.                 m->keys[n].vector=0;
  2002.                 m->keys[n].code=0;
  2003.             }
  2004.             m->map_malloc=2;
  2005.         }
  2006.         if(m->map_end)
  2007.             break;
  2008.         m=m->map_next;
  2009.     }
  2010. }
  2011.  
  2012. static void
  2013. make_keymap FUN1(char *,mapname)
  2014. {
  2015.     char *ptr;
  2016.     int num;
  2017.     struct keymap *linkmap;
  2018.     extern char *strdup();
  2019.  
  2020.     for(ptr=mapname;*ptr && *ptr!=' ';ptr++)
  2021.         ;
  2022.     linkmap=0;
  2023.     if(*ptr) {
  2024.         *ptr++='\0';
  2025.         for(num=0;num<num_maps;num++) {
  2026.             if(!strcmp(map_names[num],ptr)) {
  2027.                 linkmap=the_maps[num];
  2028.                 break;
  2029.             }
  2030.         }
  2031.     }
  2032.     for(num=0;num<num_maps;num++) {
  2033.         if(!strcmp(map_names[num],mapname)) {
  2034.             clear_keymap(the_maps[num]);
  2035.             return;
  2036.         }
  2037.     }
  2038.  
  2039.     the_maps=ck_realloc(the_maps,(num_maps+1)*sizeof(struct keymap *));
  2040.     the_maps[num_maps]=ck_malloc(sizeof(struct keymap));
  2041.     the_maps[num_maps]->map_next=linkmap;
  2042.     the_maps[num_maps]->map_end=1;
  2043.     the_maps[num_maps]->map_dense=1;
  2044.     the_maps[num_maps]->lochr='\0';
  2045.     the_maps[num_maps]->hichr='\0';
  2046.     the_maps[num_maps]->keys=ck_malloc(sizeof(struct key));
  2047.     the_maps[num_maps]->keys[0].vector=0;
  2048.     the_maps[num_maps]->keys[0].code=0;
  2049.  
  2050.  
  2051.     map_names=ck_realloc(map_names,(num_maps+1)*sizeof(char *));
  2052.     map_names[num_maps]=strdup(mapname);
  2053.     num_maps++;
  2054. }
  2055.  
  2056.  
  2057. static void
  2058. read_cmds_cmd FUN1(FILE *,fp)
  2059. {
  2060.     char *ptr;
  2061.  
  2062.     while(fgets(print_buf,300,fp)) {
  2063.         if(ptr=rindex(print_buf,'\n'))
  2064.             *ptr='\0';
  2065.         execute_cmd(print_buf);
  2066.     }
  2067. }
  2068.  
  2069. static void
  2070. write_cmd FUN1(FILE *,fp)
  2071. {
  2072.     (*write_file)(fp,0);
  2073.     modified=0;
  2074. }
  2075.  
  2076. static void
  2077. read_cmd FUN1(FILE *,fp)
  2078. {
  2079.     (*read_file)(fp,0);
  2080. }
  2081.  
  2082. static void
  2083. read_merge_cmd FUN1(FILE *,fp)
  2084. {
  2085.     (*read_file)(fp,1);
  2086. }
  2087.  
  2088. static void
  2089. write_reg_cmd FUN2(FILE *,fp,struct rng *,rng)
  2090. {
  2091.     (*write_file)(fp,rng);
  2092. }
  2093.  
  2094. static void
  2095. sort_region_cmd FUN1(char *,ptr)
  2096. {
  2097.     struct cmp {
  2098.         char mult;
  2099.         CELLREF row;
  2100.         CELLREF col;
  2101.     };
  2102.  
  2103.     struct rng tmp_rng;
  2104.  
  2105.     extern struct rng sort_rng;
  2106.     extern struct rng sort_ele;
  2107.     extern struct cmp *sort_keys;
  2108.     extern int sort_keys_num;
  2109.     extern int sort_keys_alloc;
  2110.     extern void sort_region EXT0();
  2111.  
  2112.     if(get_abs_rng(&ptr,&sort_rng)) {
  2113.         error_msg("Can't find a range to sort in %s", ptr);
  2114.         return;
  2115.     }
  2116.  
  2117.     cur_row=sort_rng.lr;
  2118.     cur_col=sort_rng.lc;
  2119.  
  2120.     while(*ptr==' ')
  2121.         ptr++;
  2122.     if(!*ptr) {
  2123.         sort_ele.lr=0;
  2124.         sort_ele.lc=0;
  2125.         sort_ele.hr=0;
  2126.         sort_ele.hc=0;
  2127.     } else if(!parse_cell_or_range(&ptr,&sort_ele)) {
  2128.         error_msg("Can't parse elements in %s",ptr);
  2129.         return;
  2130.     } else {
  2131.         sort_ele.lr-=sort_rng.lr;
  2132.         sort_ele.lc-=sort_rng.lc;
  2133.         sort_ele.hr-=sort_rng.lr;
  2134.         sort_ele.hc-=sort_rng.lc;
  2135.     }
  2136.  
  2137.     sort_keys_num=0;
  2138.     while(*ptr==' ')
  2139.         ptr++;
  2140.     for(;*ptr;) {
  2141.         if(sort_keys_num==sort_keys_alloc) {
  2142.             sort_keys_alloc++;
  2143.             if(sort_keys_alloc>1)
  2144.               {
  2145.  
  2146.                 sort_keys=ck_realloc(sort_keys,sort_keys_alloc*sizeof(struct cmp));
  2147. }
  2148.             else
  2149.                 sort_keys=ck_malloc(sizeof(struct cmp));
  2150.         }
  2151.         sort_keys[sort_keys_num].mult=1;
  2152.         if(*ptr=='+')
  2153.             ptr++;
  2154.         else if(*ptr=='-') {
  2155.             sort_keys[sort_keys_num].mult= -1;
  2156.             ptr++;
  2157.         }
  2158.         if(!*ptr) {
  2159.             sort_keys[sort_keys_num].row=0;
  2160.             sort_keys[sort_keys_num].col=0;
  2161.             sort_keys_num++;
  2162.             break;
  2163.         }
  2164.         if(!parse_cell_or_range(&ptr,&tmp_rng) || tmp_rng.lr!=tmp_rng.hr || tmp_rng.lc!=tmp_rng.hc) {
  2165.             error_msg("Can't parse key #%d in %s",sort_keys_num+1,ptr);
  2166.             sort_keys_num= -1;
  2167.             return;
  2168.         }
  2169.         sort_keys[sort_keys_num].row=tmp_rng.lr - sort_rng.lr;
  2170.         sort_keys[sort_keys_num].col=tmp_rng.lc - sort_rng.lc;
  2171.         sort_keys_num++;
  2172.  
  2173.         while(*ptr==' ')
  2174.             ptr++;
  2175.     }
  2176.     if(sort_keys_num==0) {
  2177.         if(sort_keys_alloc==0) {
  2178.             sort_keys_alloc++;
  2179.             sort_keys=ck_malloc(sizeof(struct cmp));
  2180.         }
  2181.         sort_keys[0].mult=1;
  2182.         sort_keys[0].row=0;
  2183.         sort_keys[0].col=0;
  2184.         sort_keys_num++;
  2185.     }
  2186.     sort_region();
  2187.     disp_scrn();
  2188. }
  2189.  
  2190. static void
  2191. set_var FUN1(char *,ptr)
  2192. {
  2193.     int num;
  2194.     char *ret;
  2195.     extern char *new_var_value EXT3(char *, int, char *);
  2196.  
  2197.     while(*ptr==' ')
  2198.         ptr++;
  2199.     for(num=0;ptr[num] && ptr[num]!=' ';num++)
  2200.             ;
  2201.     modified=1;
  2202.     if(!ptr[num])
  2203.         ret=new_var_value(ptr,num,(char *)0);
  2204.     else
  2205.         ret=new_var_value(ptr,num,&ptr[num+1]);
  2206.     if(ret)
  2207.         error_msg("Can't set-variable %s: %s\n",ptr,ret);
  2208. }
  2209.  
  2210. static void
  2211. show_var FUN1(char *,ptr)
  2212. {
  2213.     struct var *v;
  2214.     int num;
  2215.  
  2216.     while(*ptr==' ')
  2217.         ptr++;
  2218.     for(num=0;ptr[num] && ptr[num]!=' ';num++)
  2219.             ;
  2220.  
  2221.     v=find_var(ptr,num);
  2222.     if(!v || v->var_flags==VAR_UNDEF) {
  2223.         error_msg("There is no '%s'",ptr);
  2224.         return;
  2225.     }
  2226. #ifdef A0_REFS
  2227.     if(v->v_rng.lr!=v->v_rng.hr || v->v_rng.lc!=v->v_rng.hc)
  2228.         /* FOO */sprintf(print_buf,"%s $%s$%u:$%s$%u",v->var_name,col_to_str(v->v_rng.lc),v->v_rng.lr,col_to_str(v->v_rng.hc),v->v_rng.hr);
  2229.     else
  2230.         /* FOO */sprintf(print_buf,"%s $%s$%u",v->var_name,col_to_str(v->v_rng.lc),v->v_rng.lr);
  2231. #else
  2232.     sprintf(print_buf,"%s %s",v->var_name,range_name(&(v->v_rng)));
  2233. #endif
  2234.     info_msg(print_buf);
  2235.     set_line(&in_line[1],print_buf);
  2236. }
  2237.  
  2238. static void
  2239. show_a_var FUN2(char *,name, struct var *,v)
  2240. {
  2241.     if(v->var_flags==VAR_UNDEF)
  2242.         return;
  2243. #ifdef A0_REFS
  2244.     if(v->v_rng.lr!=v->v_rng.hr || v->v_rng.lc!=v->v_rng.hc)
  2245.         /* FOO */text_line("%-20s $%s$%u:$%s$%u",v->var_name,col_to_str(v->v_rng.lc),v->v_rng.lr,col_to_str(v->v_rng.hc),v->v_rng.hr);
  2246.     else
  2247.         /* FOO */text_line("%-20s  $%s$%u",v->var_name,col_to_str(v->v_rng.lc),v->v_rng.lr);
  2248. #else
  2249.     text_line("%-20s  %s",v->var_name,range_name(&(v->v_rng)));
  2250. #endif
  2251. }
  2252.  
  2253. static void
  2254. show_all_var FUN0()
  2255. {
  2256.     extern void text_start EXT0();
  2257.     extern void text_finish EXT0();
  2258.  
  2259.     text_start();
  2260.     for_all_vars(show_a_var);
  2261.     text_finish();
  2262. }
  2263.  
  2264. static void
  2265. shift_cell_cursor FUN1(int, dirn)
  2266. {
  2267.     CELLREF c;
  2268.     int w = 0;
  2269.     int over,down;
  2270.  
  2271.     over=colmagic[dirn]*how_many;
  2272.     down=rowmagic[dirn]*how_many;
  2273.     if(over>0) {
  2274.         c=cucol;
  2275.         while(c<MAX_COL && over-->0) {
  2276.             c++;
  2277.             while((w=get_width(c))==0 && c<MAX_COL)
  2278.                 c++;
  2279.         }
  2280.         if(over>0 || c==cucol || w==0) {
  2281.             error_msg("Can't go right");
  2282.             return;
  2283.         }
  2284.     } else if(over<0) {
  2285.         c=cucol;
  2286.         while(c>MIN_COL && over++<0) {
  2287.             --c;
  2288.             while((w=get_width(c))==0 && c>MIN_COL)
  2289.                 --c;
  2290.         }
  2291.         if(over<0 || c==cucol || w==0) {
  2292.             error_msg("Can't go left");
  2293.             return;
  2294.         }
  2295.     } else
  2296.         c = cucol;
  2297.     if(down>0) {
  2298.         if(curow>MAX_ROW-down) {
  2299.             error_msg("Can't go down");
  2300.             return;
  2301.         }
  2302.     } else if(down<0) {
  2303.         if(curow<MIN_ROW-down) {
  2304.             error_msg("Can't go up");
  2305.             return;
  2306.         }
  2307.     }
  2308.     move_cell_cursor(curow+down,c);
  2309. }
  2310.  
  2311. static void
  2312. scan_cell_cursor FUN1(int,magic)
  2313. {
  2314.     CELLREF pos,pos_end,pos_inc;
  2315.     CELL *cp;
  2316.     int over,down;
  2317.  
  2318.     extern CELLREF max_row(),max_col();
  2319.  
  2320.     over=colmagic[magic]*how_many;
  2321.     down=rowmagic[magic]*how_many;
  2322.     if(over) {
  2323.         if(over>0) {
  2324.             pos=max_col(curow);
  2325.             pos_end=MIN_COL;
  2326.             pos_inc= -1;
  2327.         } else {
  2328.             pos=MIN_COL;
  2329.             pos_end=max_col(curow);
  2330.             pos_inc=1;
  2331.         }
  2332.         for(;;) {
  2333.             for(;((!(cp=find_cell(curow,pos)) || !GET_TYP(cp)));pos+=pos_inc) {
  2334.                 if(pos==pos_end) {
  2335.                     how_many=1;
  2336.                     pos=MIN_COL;
  2337.                     break;
  2338.                 }
  2339.             }
  2340.             if(--how_many==0)
  2341.                 break;
  2342.             pos+=pos_inc;
  2343.         }
  2344.         move_cell_cursor(curow,pos);
  2345.     } else {
  2346.         if(down>0) {
  2347.             pos=max_row(cucol);
  2348.             pos_end=MIN_ROW;
  2349.             pos_inc= -1;
  2350.         } else {
  2351.             pos=MIN_ROW;
  2352.             pos_end=max_row(cucol);
  2353.             pos_inc=1;
  2354.         }
  2355.         for(;;) {
  2356.             for(;(!(cp=find_cell(pos,cucol)) || !GET_TYP(cp));pos+=pos_inc) {
  2357.                 if(pos==pos_end) {
  2358.                     how_many=1;
  2359.                     pos=MIN_ROW;
  2360.                     break;
  2361.                 }
  2362.             }
  2363.             if(--how_many==0)
  2364.                 break;
  2365.             pos+=pos_inc;
  2366.         }
  2367.  
  2368.         move_cell_cursor(pos,cucol);
  2369.     }
  2370. }
  2371.  
  2372.  
  2373. char *
  2374. fmt_to_str FUN1(int, fmt)
  2375. {
  2376.     char *ptr;
  2377.     static char buf[30];
  2378.     char nbuf[10];
  2379.  
  2380.     if(fmt==FMT_DEF)
  2381.         return "default";
  2382.     if(fmt==FMT_HID)
  2383.         return "hidden";
  2384.     if(fmt==FMT_GPH)
  2385.         return "graph";
  2386.     if((fmt&PRC_FLT)==PRC_FLT)
  2387.         strcpy(nbuf,"float");
  2388.     else
  2389.         sprintf(nbuf,"%d",(fmt&PRC_FLT));
  2390.     switch(fmt|PRC_FLT) {
  2391.     case FMT_USR:
  2392.         ptr="user-";
  2393.         sprintf(nbuf,"%d",(fmt&PRC_FLT)+1);
  2394.         break;
  2395.     case FMT_GEN:
  2396.         ptr="general.";
  2397.         break;
  2398.     case FMT_DOL:
  2399.         ptr="dollar.";
  2400.         break;
  2401.     case FMT_CMA:
  2402.         ptr="comma.";
  2403.         break;
  2404.     case FMT_PCT:
  2405.         ptr="percent.";
  2406.         break;
  2407.     case FMT_FXT:
  2408.         if((fmt&PRC_FLT)==0)
  2409.             return "integer";
  2410.         if(fmt==FMT_FXT)
  2411.             return "decimal";
  2412.         ptr="fixed.";
  2413.         break;
  2414.     case FMT_EXP:
  2415.         ptr="exponent.";
  2416.         break;
  2417.     default:
  2418.         error_msg("Unknown format %d (%x)",fmt,fmt);
  2419.         ptr="UNKNOWN";
  2420.         break;
  2421.     }
  2422.     sprintf(buf,"%s%s",ptr,nbuf);
  2423.     return buf;
  2424. }
  2425.  
  2426. struct fmt {
  2427.     int fmt;
  2428.     char **strs;
  2429. };
  2430.  
  2431. static char *def_names[] = {"default","def","D",0};
  2432. static char *hid_names[] = {"hidden","hid","H",0};
  2433. static char *gph_names[] = {"graph","gph","*",0};
  2434. static char *int_names[] = {"integer","int","I",0};
  2435. static char *dec_names[] = {"decimal","dec",0};
  2436.  
  2437. static struct fmt simple[] = {
  2438.     { FMT_DEF,       def_names },
  2439.     { FMT_HID,       hid_names },
  2440.     { FMT_GPH,       gph_names },
  2441.     { FMT_FXT-PRC_FLT, int_names },
  2442.     { FMT_FXT,       dec_names },
  2443.     { 0,           0}
  2444. };
  2445.  
  2446. char *gen_names[] = {"general.","gen.","G",0};
  2447. char *dol_names[] = {"dollar.","dol.","$",0};
  2448. char *cma_names[] = {"comma.","com.",",",0};
  2449. char *pct_names[] = {"percent.","pct.","%",0};
  2450. char *fxt_names[] = {"fixed.","fxt.","F",0};
  2451. char *exp_names[] = {"exponent.","exp.","E",0};
  2452.  
  2453. static struct fmt withprec[] = {
  2454.     { FMT_GEN-PRC_FLT, gen_names },
  2455.     { FMT_DOL-PRC_FLT, dol_names },
  2456.     { FMT_CMA-PRC_FLT, cma_names },
  2457.     { FMT_PCT-PRC_FLT, pct_names },
  2458.     { FMT_FXT-PRC_FLT, fxt_names },
  2459.     { FMT_EXP-PRC_FLT, exp_names },
  2460.     { 0,           0 }
  2461. };
  2462.  
  2463. static int
  2464. str_to_fmt FUN1(char *,ptr)
  2465. {
  2466.     struct fmt *f;
  2467.     char **strs;
  2468.     int n;
  2469.     int ret;
  2470.     char *p1,*p2;
  2471.  
  2472.     for(f=simple;f->strs;f++) {
  2473.         for(strs=f->strs;*strs;strs++) {
  2474.             if(*ptr!=**strs)
  2475.                 continue;
  2476.             for(p1=ptr,p2= *strs;*p1==*p2 && *p1;p1++,p2++)
  2477.                 ;
  2478.             if(*p1=='\0' && *p2=='\0')
  2479.                 return f->fmt;
  2480.         }
  2481.     }
  2482.     if(!strncmp(ptr,"user-",5)) {
  2483.         ptr+=5;
  2484.         n=astol(&ptr);
  2485.         if(*ptr || n<1 || n>16)
  2486.             return -1;
  2487.         return n-1-PRC_FLT+FMT_USR;
  2488.     }
  2489.     for(f=withprec,ret=0;!ret && f->strs;f++) {
  2490.         for(strs=f->strs;*strs;strs++) {
  2491.             if(*ptr!=**strs)
  2492.                 continue;
  2493.             for(p1=ptr,p2= *strs;*p2 && *p1==*p2;p1++,p2++)
  2494.                 ;
  2495.             if(!*p2) {
  2496.                 ret=f->fmt;
  2497.                 ptr=p1;
  2498.                 break;
  2499.             }
  2500.         }
  2501.     }
  2502.  
  2503.     if(!ret || !*ptr)
  2504.         return -1;
  2505.     if(!strcmp(ptr,"float") || !strcmp(ptr,"f")) {
  2506.         n=PRC_FLT;
  2507.     } else {
  2508.         n=astol(&ptr);
  2509.         if(*ptr || n<0 || n>14)
  2510.             return -1;
  2511.     }
  2512.     return ret+n;
  2513. }
  2514.  
  2515. char *
  2516. jst_to_str FUN1(int, jst)
  2517. {
  2518.     if(jst==JST_DEF)
  2519.         return "default";
  2520.     if(jst==JST_LFT)
  2521.         return "left";
  2522.     if(jst==JST_RGT)
  2523.         return "right";
  2524.     if(jst==JST_CNT)
  2525.         return "center";
  2526.     return "unknown";
  2527. }
  2528.  
  2529. static int
  2530. chr_to_jst FUN1(int, chr)
  2531. {
  2532.     if(chr=='d' || chr=='D')
  2533.         return JST_DEF;
  2534.     if(chr=='l' || chr=='L')
  2535.         return JST_LFT;
  2536.     if(chr=='r' || chr=='R')
  2537.         return JST_RGT;
  2538.     if(chr=='c' || chr=='C')
  2539.         return JST_CNT;
  2540.     return -1;
  2541. }
  2542.  
  2543. /* parse a range, then turn it into an absolute rng */
  2544. static int
  2545. get_abs_rng FUN2(char **,pptr, struct rng *,retp)
  2546. {
  2547.     unsigned char n;
  2548.  
  2549.     while(**pptr==' ')
  2550.         (*pptr)++;
  2551.     if(!**pptr)
  2552.         return 1;
  2553.     cur_row=curow;
  2554.     cur_col=cucol;
  2555.     n=parse_cell_or_range(pptr,retp);
  2556.     if(!n) {
  2557.         struct var *v;
  2558.         char *ptr;
  2559.  
  2560.         ptr= *pptr;
  2561.         while(ptr[n] && ptr[n]!=' ')
  2562.             n++;
  2563.         v=find_var(ptr,n);
  2564.         if(!v)
  2565.             return 1;
  2566.         (*pptr)+=n;
  2567.         *retp= v->v_rng;
  2568.     }
  2569.     return 0;
  2570. }
  2571.  
  2572. static void desc_map FUN1(struct keymap *,map)
  2573. {
  2574.     int n;
  2575.     int maxn;
  2576.  
  2577.     
  2578.     text_start();
  2579.     while(map) {
  2580.         maxn=1+map->hichr-map->lochr;
  2581.         if(map->map_dense)
  2582.             text_line("%s - %s: %d %d %s",
  2583.                   char_to_string(map->lochr),
  2584.                    char_to_string(map->hichr),
  2585.                   map->keys[0].vector,
  2586.                    map->keys[0].code,
  2587.                    map->keys[0].vector==255 ? "vector" : the_funcs[map->keys[0].vector][map->keys[0].code].func_name);
  2588.         else
  2589.             for(n=0;n<maxn;n++)
  2590.                 text_line("%s: %d %d %s",
  2591.                       char_to_string(map->lochr+n),
  2592.                       map->keys[n].vector,
  2593.                       map->keys[n].code,
  2594.                       map->keys[n].vector==255 ? "vector" : the_funcs[map->keys[n].vector][map->keys[n].code].func_name);
  2595.         map=map->map_end ? 0 : map->map_next;
  2596.     }
  2597.     text_finish();
  2598. }
  2599.  
  2600. #if 0
  2601. static char *
  2602. key_name FUN1(int,key)
  2603. {
  2604. /*    int mac;
  2605.  
  2606.     if(main_map[key]==BOUND_MACRO) {
  2607.         for(mac=0;mac<n_bound_macros;mac++)
  2608.             if(bound_macros[mac].c==key)
  2609.                 return range_name(&(bound_macros[mac].r));
  2610. #ifdef TEST
  2611.         error_msg("Unknown bound macro on key %d",key);
  2612. #endif
  2613.     }
  2614.     return cmd_funcs[main_map[key]].func_name; */
  2615. }
  2616. #endif
  2617.  
  2618. static void
  2619. set_usr_fmt FUN1(char *,fmtstr)
  2620. {
  2621.     int u_num;
  2622.     char *ptr;
  2623.     static struct line usr_line;
  2624.     struct line tmp_line;
  2625.     char *tmp_ptr;
  2626.     char *data_buf[9];
  2627.     int i;
  2628.     static char *names[9]= {
  2629.         "Positive header",
  2630.         "Negative header",
  2631.         "Positive trailer",
  2632.         "Negative trailer",
  2633.         "Zero",
  2634.         "Comma",
  2635.         "Decimal point",
  2636.         "Precision",
  2637.         "Scale-factor"
  2638.     };
  2639.  
  2640.     tmp_line.buf=ck_malloc(10);
  2641.     tmp_line.alloc=10;
  2642.     tmp_ptr=tmp_line.buf;
  2643.  
  2644.     ptr=fmtstr;
  2645.     u_num=astol(&ptr);
  2646.     if(u_num<1 || u_num>16 || *ptr!='\0') {
  2647.         error_msg("Unknown number %s",fmtstr);
  2648.         return;
  2649.     }
  2650.     --u_num;
  2651.  
  2652.     get_usr_stats(u_num,data_buf);
  2653.     for(i=0;i<9;i++) {
  2654.         int slen;
  2655.         int prevlen;
  2656.  
  2657.         set_line(&usr_line,data_buf[i]);
  2658.         if(get_inp_line(names[i],&usr_line)>1)
  2659.             return;
  2660.  
  2661.         slen=strlen(usr_line.buf);
  2662.         if(tmp_line.alloc<=(tmp_ptr-tmp_line.buf)+slen) {
  2663.             prevlen=tmp_ptr-tmp_line.buf;
  2664.             tmp_line.alloc+=slen+1;
  2665.  
  2666.             tmp_line.buf=ck_realloc(tmp_line.buf,tmp_line.alloc);
  2667.             tmp_ptr=tmp_line.buf+prevlen;
  2668.         }
  2669.         strcpy(tmp_ptr,usr_line.buf);
  2670.         data_buf[i]=tmp_ptr;
  2671.         while(*tmp_ptr!='\0')
  2672.             tmp_ptr++;
  2673.         tmp_ptr++;
  2674.     }
  2675.  
  2676.     set_usr_stats(u_num, data_buf);
  2677.     free(tmp_line.buf);
  2678.     disp_scrn();
  2679. }
  2680.  
  2681.  
  2682. /* Modify this to write out *all* the options */
  2683. void
  2684. write_mp_options FUN1(FILE *,fp)
  2685. {
  2686.     fprintf(fp,"O;%sauto;%sbackground;ticks %d\n",
  2687.         auto_recalc ? "" : "no",
  2688.         bkgrnd_recalc ? "" : "no",
  2689.         signal_ticks/TIMER_MULT);
  2690. }
  2691.  
  2692. void
  2693. read_mp_options FUN1(char *,str)
  2694. {
  2695.     char *np;
  2696.  
  2697.     while(np=index(str,';')) {
  2698.         *np='\0';
  2699.         (void)do_set_option(str);
  2700.         *np++=';';
  2701.         str=np;
  2702.     }
  2703.     if(np=rindex(str,'\n'))
  2704.         *np='\0';
  2705.     (void)do_set_option(str);
  2706. }
  2707.  
  2708. void
  2709. set_options FUN1(char *,ptr)
  2710. {
  2711.     if(do_set_option(ptr))
  2712.         recenter_cur_win();
  2713. }
  2714.  
  2715. static void
  2716. show_options FUN0()
  2717. {
  2718.     int n;
  2719.     int fmts;
  2720.     char *data_buf[9];
  2721.  
  2722.     extern char *strdup();
  2723.     extern void text_start EXT0();
  2724.     extern void text_finish EXT0();
  2725.     extern void show_window_options();
  2726.  
  2727.     n=auto_recalc;
  2728.     text_start();
  2729.  
  2730.     text_line("auto-recalculation: %s        Recalculate in background: %s",
  2731.          n ? " on" : "off",bkgrnd_recalc ? "on" : "off");
  2732.     text_line("make backup files:  %s        Copy files into backups:   %s",
  2733.         __make_backups ? " on" : "off",__backup_by_copying ? "on" : "off");
  2734.  
  2735.     text_line("Asynchronous updates every %u ???",
  2736.         signal_ticks/TIMER_MULT);
  2737.  
  2738.     text_line("Print width:      %5u",print_width);
  2739.  
  2740.     text_line("");
  2741.  
  2742.     (*show_file_opts)();
  2743.  
  2744.     text_line("");
  2745.     show_window_options();
  2746.     text_line("");
  2747.  
  2748.     fmts=usr_set_fmts();
  2749.     if(fmts) {
  2750.         text_line("User-defined formats:");
  2751.         text_line("Fmt    +Hdr    -Hdr   +Trlr   -Trlr    Zero   Comma Decimal  Prec         Scale");
  2752.         for(n=0;n<16;n++) {
  2753.             if(fmts&(1<<n)) {
  2754.                 get_usr_stats(n,data_buf);
  2755.                 text_line("%3d %7s %7s %7s %7s %7s %7s %7s %5s %13s",
  2756.                   n+1,
  2757.                   data_buf[0],
  2758.                   data_buf[1],
  2759.                   data_buf[2],
  2760.                   data_buf[3],
  2761.                   data_buf[4],
  2762.                   data_buf[5],
  2763.                   data_buf[6],
  2764.                   data_buf[7],
  2765.                   data_buf[8]);
  2766.             }
  2767.         }
  2768.     } else
  2769.         text_line("No user-defined formats have been defined");
  2770.  
  2771.     text_finish();
  2772. }
  2773.  
  2774. static int
  2775. do_set_option FUN1(char *,ptr)
  2776. {
  2777.     int set_opt = 1;
  2778.     extern int set_window_option();
  2779.  
  2780.     while(*ptr==' ')
  2781.         ptr++;
  2782.     if(!strincmp("no",ptr,2)) {
  2783.         ptr+=2;
  2784.         set_opt=0;
  2785.         while(*ptr==' ')
  2786.             ptr++;
  2787.     }
  2788.     if(!stricmp("auto",ptr)) {
  2789.         auto_recalc = set_opt;
  2790.         return 0;
  2791.     }
  2792.     if(!stricmp("bkgrnd",ptr) || !stricmp("background",ptr)) {
  2793.         bkgrnd_recalc = set_opt;
  2794.         return 0;
  2795.     }
  2796.     if(!stricmp("backup",ptr)) {
  2797.         __make_backups = set_opt;
  2798.         return 0;
  2799.     }
  2800.     if(!stricmp("bkup_copy",ptr)) {
  2801.         __backup_by_copying = set_opt;
  2802.         return 0;
  2803.     }
  2804.     if(set_opt && !strincmp("ticks ",ptr,6)) {
  2805.         extern unsigned ualarm EXT2(unsigned int, unsigned int);
  2806.  
  2807.         ptr+=6;
  2808.         signal_ticks= astol(&ptr) * TIMER_MULT;
  2809. #ifndef __TURBOC__
  2810.         if(timer_active)
  2811.             ualarm(signal_ticks,signal_ticks);
  2812. #endif
  2813.         return 0;
  2814.     }
  2815.     if(set_opt && !strincmp("print ",ptr,6)) {
  2816.         ptr+=6;
  2817.         print_width=astol(&ptr);
  2818.         return 0;
  2819.     }
  2820.     if(set_opt && !strincmp("file ",ptr,5)) {
  2821. #ifdef USE_DLD
  2822.         char *tmpstr;
  2823.         extern char *strdup();
  2824.  
  2825.         ptr+=5;
  2826.         tmpstr=ck_malloc(strlen(ptr)+20);
  2827.         if(io_name) {
  2828.             sprintf(tmpstr, "%s.o", ptr);
  2829.             if(dld_unlink_by_file(tmpstr,0)) {
  2830.                 error_msg("Couldn't unlink old file format %s: %s",io_name,(dld_errno < 0 || dld_errno > dld_nerr) ? "Unknown error" : dld_errlst[dld_errno]);
  2831.                 goto bad_file;
  2832.             }
  2833.             free(io_name);
  2834.         }
  2835.         if(!stricmp(ptr,"panic")) {
  2836.             io_name=0;
  2837.             read_file      = panic_read_file;
  2838.             write_file     = panic_write_file;
  2839.             set_file_opts  = panic_set_options;
  2840.             show_file_opts = panic_show_options;
  2841.             free(tmpstr);
  2842.             return 0;
  2843.         }
  2844.         io_name=strdup(ptr);
  2845.         sprintf(tmpstr, "%s.o", ptr);
  2846.         if(dld_link(tmpstr)) {
  2847.             error_msg("Couldn't link new file format %s: %s",io_name,(dld_errno < 0 || dld_errno > dld_nerr) ? "Unknown error" : dld_errlst[dld_errno]);
  2848.             goto bad_file;
  2849.         }
  2850.         if(dld_link("libc.a"))
  2851.             error_msg("Couldn't link libc.a");
  2852.         if(dld_link("libm.a"))
  2853.             error_msg("Couldn't link libm.a");
  2854.  
  2855.         sprintf(tmpstr, "%s_read_file",ptr);
  2856.         read_file=dld_function_executable_p(tmpstr) ? dld_get_func(tmpstr) : 0;
  2857.         sprintf(tmpstr, "%s_write_file",ptr);
  2858.         write_file=dld_function_executable_p(tmpstr) ? dld_get_func(tmpstr) : 0;
  2859.  
  2860.         sprintf(tmpstr, "%s_set_options",ptr);
  2861.         set_file_opts=(int(*)())(dld_function_executable_p(tmpstr) ? dld_get_func(tmpstr) : 0);
  2862.         sprintf(tmpstr, "%s_show_options",ptr);
  2863.         show_file_opts=dld_function_executable_p(tmpstr) ? dld_get_func(tmpstr) : 0;
  2864.  
  2865.         if(   !read_file
  2866.            || !write_file
  2867.            || !set_file_opts
  2868.            || !show_file_opts) {
  2869.                char **missing;
  2870.             int n;
  2871.  
  2872.             missing=dld_list_undefined_sym();
  2873.                text_start();
  2874.             text_line("Undefined symbols in file format %s:",ptr);
  2875.             text_line("");
  2876.             for(n=0;n<dld_undefined_sym_count;n++)
  2877.                 text_line("%s",missing[n]);
  2878.             text_line("");
  2879.             text_finish();
  2880.             free(missing);
  2881.             error_msg("File format %s has undefined symbols: not loaded",ptr);
  2882.     bad_file:
  2883.             sprintf(tmpstr, "%s.o",io_name);
  2884.             dld_unlink_by_file(io_name,0);
  2885.             if(io_name)
  2886.                 free(io_name);
  2887.             io_name=0;
  2888.             read_file=panic_read_file;
  2889.             write_file=panic_write_file;
  2890.             set_file_opts=panic_set_options;
  2891.             show_file_opts=panic_show_options;
  2892.         }
  2893.         free(tmpstr);
  2894. #else
  2895.         ptr+=5;
  2896.         if(!stricmp("sylk",ptr)) {
  2897.             read_file     = sylk_read_file;
  2898.             write_file    = sylk_write_file;
  2899.             set_file_opts = sylk_set_options;
  2900.             show_file_opts= sylk_show_options;
  2901.         } else if(!stricmp("sc",ptr)) {
  2902.             read_file     = sc_read_file;
  2903.             write_file    = sc_write_file;
  2904.             set_file_opts = sc_set_options;
  2905.             show_file_opts= sc_show_options;
  2906.         } else if(!stricmp("panic",ptr)) {
  2907.             read_file     = panic_read_file;
  2908.             write_file    = panic_write_file;
  2909.             set_file_opts = panic_set_options;
  2910.             show_file_opts= panic_show_options;
  2911.         } else if(!stricmp("list",ptr)) {
  2912.             read_file     = list_read_file;
  2913.             write_file    = list_write_file;
  2914.             set_file_opts = list_set_options;
  2915.             show_file_opts= list_show_options;
  2916.             /*if(ptr[4]) {
  2917.                 ptr+=4;
  2918.                 sl_sep=string_to_char(&ptr);
  2919.             } */
  2920.         } else
  2921.             error_msg("Unknown file format %s",ptr);
  2922. #endif
  2923.         return 0;
  2924.     }
  2925. #ifdef USE_DLD
  2926.     else if(!strincmp(ptr,"load ",5)) {
  2927.         char *tmpstr;
  2928.         struct function *new_funs;
  2929.         struct cmd_func *new_cmds;
  2930.         struct keymap **new_maps;
  2931.         void (*init_cmd) EXT0();
  2932.  
  2933.         extern unsigned long dld_get_symbol EXT1(char *);
  2934.         extern void add_usr_funs EXT1(struct function *);
  2935.  
  2936.         ptr+=5;
  2937.         tmpstr=ck_malloc(strlen(ptr)+20);
  2938.         sprintf(tmpstr,"%s.o",ptr);
  2939.         if(dld_link(tmpstr)) {
  2940.             error_msg("Couldn't link %s: %s",tmpstr,(dld_errno < 0 || dld_errno > dld_nerr) ? "Unknown error" : dld_errlst[dld_errno]);
  2941.             free(tmpstr);
  2942.             return 0;
  2943.         }
  2944.         if(dld_link("libc.a"))
  2945.             error_msg("Couldn't link libc.a");
  2946.         if(dld_link("libm.a"))
  2947.             error_msg("Couldn't link libm.a");
  2948.  
  2949.         if(dld_undefined_sym_count) {
  2950.                char **missing;
  2951.             int n;
  2952.  
  2953.             missing=dld_list_undefined_sym();
  2954.                text_start();
  2955.             text_line("Undefined symbols in file format %s:",ptr);
  2956.             text_line("");
  2957.             for(n=0;n<dld_undefined_sym_count;n++)
  2958.                 text_line("%s",missing[n]);
  2959.             text_line("");
  2960.             text_finish();
  2961.             free(missing);
  2962.             error_msg("%d undefined symbols in %s",dld_undefined_sym_count,ptr);
  2963.             dld_unlink_by_file(tmpstr,0);
  2964.             free(tmpstr);
  2965.             return 0;
  2966.         }
  2967.         sprintf(tmpstr,"%s_funs",ptr);
  2968.         new_funs=(struct function *)dld_get_symbol(tmpstr);
  2969.         if(new_funs)
  2970.             add_usr_funs(new_funs);
  2971.         sprintf(tmpstr,"%s_cmds", ptr);
  2972.         new_cmds=(struct cmd_func *)dld_get_symbol(tmpstr);
  2973.         if(new_cmds)
  2974.             add_usr_cmds(new_cmds);
  2975.         sprintf(tmpstr,"%s_maps", ptr);
  2976.         new_maps=(struct keymap **)dld_get_symbol(tmpstr);
  2977.         if(new_maps)
  2978.             add_usr_maps(new_maps);
  2979.         if(!new_funs && !new_cmds && !new_maps) {
  2980.             error_msg("Couldn't find anything to load in %s",ptr);
  2981.             sprintf(tmpstr,"%s.o",ptr);
  2982.             dld_unlink_by_file(tmpstr,0);
  2983.         }
  2984.         sprintf(tmpstr,"%s_init",ptr);
  2985.         init_cmd=dld_function_executable_p(tmpstr) ? dld_get_func(tmpstr) : 0;
  2986.         if(init_cmd)
  2987.             (*init_cmd)();
  2988.         free(tmpstr);
  2989.         return 0;
  2990.     }
  2991. #endif
  2992.     if(set_window_option(set_opt,ptr)==0) {
  2993.         if((*set_file_opts)(set_opt,ptr))
  2994.             error_msg("Unknown option '%s'",ptr);
  2995.         return 0;
  2996.     }
  2997.     return 1;
  2998. }
  2999.  
  3000. void
  3001. set_line FUN2(struct line *,line, char *,string)
  3002. {
  3003.     int len;
  3004.  
  3005.     if(!string) {
  3006.         if(line->alloc)
  3007.             line->buf[0]='\0';
  3008.         return;
  3009.     }
  3010.     len=strlen(string);
  3011.     if(line->alloc<=len) {
  3012.         if(len<LINE_MIN)
  3013.             len=LINE_MIN;
  3014.         else
  3015.             len++;
  3016.         line->alloc=len+1;
  3017.         if(line->buf)
  3018.           {
  3019.  
  3020.             line->buf=ck_realloc(line->buf,line->alloc);
  3021. }
  3022.         else
  3023.             line->buf=ck_malloc(line->alloc);
  3024.     }
  3025.     strcpy(line->buf,string);
  3026. }
  3027.  
  3028. static void
  3029. sprint_line FUN2N(struct line *,line, char *,fmt)
  3030. {
  3031.     va_list iggy;
  3032.     int len;
  3033.  
  3034.     len=strlen(fmt)+200;
  3035.     if(!line->alloc) {
  3036.         line->buf=ck_malloc(len);
  3037.         line->alloc=len;
  3038.     } else if(line->alloc<len) {
  3039.  
  3040.         line->buf=ck_realloc(line->buf,len);
  3041.         line->alloc=len;
  3042.     }
  3043.     var_start(iggy,fmt);
  3044.     vsprintf(line->buf,fmt,iggy);
  3045.     va_end(iggy);
  3046. }
  3047.  
  3048. static void
  3049. execute_cmd FUN1(char *,str)
  3050. {
  3051.     CELL *cp;
  3052.     struct macro *old;
  3053.     struct rng r;
  3054.     char *ptr;
  3055.  
  3056.     for(ptr=str;*ptr && *ptr!=' ';ptr++)
  3057.         ;
  3058.     if(*ptr)
  3059.         *ptr++='\0';
  3060.     else
  3061.         ptr=0;
  3062.  
  3063.     for(cur_vector=0;cur_vector<num_funcs;cur_vector++)
  3064.         for(cur_cmd= &the_funcs[cur_vector][0];cur_cmd->func_name;cur_cmd++)
  3065.             if(!stricmp(str,cur_cmd->func_name)) {
  3066.                 /* these lines stolen from map_char */
  3067.                 if(ptr) {
  3068.                     if(!cur_cmd->func_args)
  3069.                         error_msg("Ignoring extra operand to %s",cur_cmd->func_name);
  3070.                     else if(cur_cmd->func_args[0]=='n')
  3071.                         how_many=astol((char **)(&ptr));
  3072.                     else
  3073.                         macro_func_arg=ptr;
  3074.                 }
  3075.  
  3076.                 cur_chr='\0';
  3077.                 global_cmd(MAIN_MAP);
  3078.                 return;
  3079.             }
  3080.  
  3081.     if(get_abs_rng(&str,&r)) {
  3082.         error_msg("Unknown command %s",str);
  3083.         return;
  3084.     }
  3085.     if(ptr) {
  3086.         error_msg("Macros can't take arguments");
  3087.         return;
  3088.     }
  3089.  
  3090.     if(  !(cp=find_cell(r.lr,r.lc))
  3091.         || GET_TYP(cp)!=TYP_STR
  3092.        || cp->cell_str[0]=='\0')
  3093.         return;
  3094.  
  3095.     old=rmac;
  3096.     rmac=(struct macro *)obstack_alloc(¯o_stack,sizeof(struct macro));
  3097.     rmac->mac_prev=old;
  3098.     rmac->mac_rng= r;
  3099.     rmac->mac_row=r.lr;
  3100.     rmac->mac_col=r.lc;
  3101.     (void)obstack_grow(¯o_stack,cp->cell_str,1+strlen(cp->cell_str));
  3102.     rmac->mac_exe=(unsigned char *)obstack_finish(¯o_stack);
  3103.     rmac->mac_flags=0;
  3104. }
  3105.  
  3106. static void
  3107. goto_region FUN1(struct rng *,r)
  3108. {
  3109.     struct rng tmp;
  3110.  
  3111.     if(mkrow!=NON_ROW) {
  3112.         CELLREF cx,cy;
  3113.  
  3114.         set_rng(&tmp,curow,cucol,mkrow,mkcol);
  3115.         set_line(&in_line[12],range_name(&tmp));
  3116.         cx=mkrow;
  3117.         mkrow=curow;
  3118.         cy=mkcol;
  3119.         mkcol=cucol;
  3120.         (void)move_cell_cursor(cx,cy);
  3121.     } else {
  3122.         set_line(&in_line[12],cell_name(curow,cucol));
  3123.         (void)move_cell_cursor(r->lr,r->lc);
  3124.     }
  3125.     if(r->hr!=r->lr || r->hc!=r->lc) {
  3126.         mkrow=r->hr;
  3127.         mkcol=r->hc;
  3128.         cur_status();
  3129.     } else if(mkrow!=NON_ROW) {
  3130.         mkrow=NON_ROW;
  3131.         cur_status();
  3132.     }
  3133. }
  3134.  
  3135. static void
  3136. set_default FUN0()
  3137. {
  3138.     int fun;
  3139.     char *ptr;
  3140.     int num;
  3141.     char buf[20];
  3142.  
  3143.     sprintf(buf,"%d",default_width);
  3144.     set_line(&wid_line,buf);
  3145.     set_line(&fmt_line,fmt_to_str(default_fmt));
  3146.     info_msg("Alignment %s   Format %s   %srotected  Width %d",
  3147.         jst_to_str(default_jst),
  3148.         fmt_line.buf,
  3149.         default_lock==LCK_LCK ? "P" : "Unp",
  3150.         default_width);
  3151.  
  3152.     fun=get_chr_prompt("[A]lignment, [F]ormat, [P]rotection, or [W]idth  ");
  3153.     switch(fun) {
  3154.     case 'w':
  3155.     case 'W':
  3156.         if(get_inp_line("set-default-width",&wid_line))
  3157.             break;
  3158.         ptr=wid_line.buf;
  3159.         num=astol(&ptr);
  3160.         if(num<1)
  3161.             error_msg("Can't set default width to '%s'",wid_line.buf);
  3162.         else {
  3163.             default_width=num;
  3164.             recenter_all_win();
  3165.             return;
  3166.         }
  3167.         break;
  3168.  
  3169.     case 'p':
  3170.     case 'P':
  3171.         fun=get_chr_prompt("[P]rotected, or [U]nprotected");
  3172.         if(fun=='p' || fun=='P')
  3173.             default_lock= LCK_LCK;
  3174.         else if(fun=='u' || fun=='U')
  3175.             default_lock=LCK_UNL;
  3176.         else /* if(main_map<[fun]!=BREAK_CMD) */
  3177.             error_msg("Unknown char '%s'",char_to_string(fun));
  3178.         break;
  3179.  
  3180.     case 'f':
  3181.     case 'F':
  3182.         if(get_inp_line("set-default-format",&fmt_line))
  3183.             break;
  3184.         num=str_to_fmt(fmt_line.buf);
  3185.         if(num==-1 || num==FMT_DEF) {
  3186.             error_msg("Unknown format '%s'",fmt_line.buf);
  3187.             break;
  3188.         }
  3189.         default_fmt=num;
  3190.         disp_scrn();
  3191.         return;
  3192.  
  3193.     case 'a':
  3194.     case 'A':
  3195.         fun=get_chr_prompt("[L]eft, [R]ight, or [C]enter");
  3196.         num=chr_to_jst(fun);
  3197.         if(num!=-1 && num!=JST_DEF) {
  3198.             default_jst=num;
  3199.             disp_scrn();
  3200.             return;
  3201.         } else /* if(main_map[fun]!=BREAK_CMD) */
  3202.             error_msg("Unknown Alignment '%s'",char_to_string(fun));
  3203.         break;
  3204.  
  3205.     default:
  3206.         /* if(main_map[fun]!=BREAK_CMD) */
  3207.             error_msg("Unknown command '%s'",char_to_string(fun));
  3208.         /* else
  3209.             error_msg(""); */
  3210.         break;
  3211.     }
  3212.     cur_status();
  3213.     /* topclear=2; */
  3214. }
  3215.  
  3216. static void
  3217. format_area FUN1(struct rng *,f)
  3218. {
  3219.     int c;
  3220.     int fmt,jst,wid;
  3221.     CELLREF cc;
  3222.     char *locked;
  3223.     CELL *cp;
  3224.     int fun;
  3225.     char *ptr;
  3226.     extern unsigned short get_nodef_width EXT1(CELLREF);
  3227.  
  3228.     cp=find_cell(f->lr,f->lc);
  3229.     if(!cp) {
  3230.         fmt=FMT_DEF;
  3231.         jst=JST_DEF;
  3232.     } else {
  3233.         fmt=GET_FMT(cp);
  3234.         jst=GET_JST(cp);
  3235.     }
  3236.  
  3237.     wid=get_nodef_width(f->lc);
  3238.     if(wid==0)
  3239.         set_line(&wid_line,"default");
  3240.     else
  3241.         sprint_line(&wid_line,"%d",wid-1);
  3242.  
  3243.     set_line(&fmt_line,fmt_to_str(fmt));
  3244.     if(cp) {
  3245.         if(GET_LCK(cp)==LCK_DEF)
  3246.             locked = (default_lock==LCK_UNL ? "default unprotected" : "default protected");
  3247.         else if(GET_LCK(cp)==LCK_UNL)
  3248.             locked = "unprotected";
  3249.         else if(GET_LCK(cp)==LCK_LCK)
  3250.             locked = "protected";
  3251.         else
  3252.             locked = "Huh What?";
  3253.     } else
  3254.         locked = (default_lock==LCK_UNL ? "default unprotected" : "default protected");
  3255.  
  3256.     info_msg("Alignment %s   Format %s   Width %s   %s",
  3257.         jst_to_str(jst),
  3258.         fmt_line.buf,
  3259.         wid_line.buf,
  3260.         locked);
  3261.  
  3262.     fun=get_chr_prompt("[A]lignment, [F]ormat, [P]rotection, or [W]idth  ");
  3263.     switch(fun) {
  3264.     case 'f':
  3265.     case 'F':
  3266.         if(get_inp_line("set-format",&fmt_line))
  3267.             break;
  3268.         fmt=str_to_fmt(fmt_line.buf);
  3269.         if(fmt!=-1)
  3270.             format_region(f,fmt,-1);
  3271.         else
  3272.             error_msg("Unknown format '%s'",fmt_line.buf);
  3273.         break;
  3274.  
  3275.     case 'a':
  3276.     case 'A':
  3277.         c=get_chr_prompt("Align [L]eft, [R]ight, [C]enter, or [D]efault");
  3278.         fun=chr_to_jst(c);
  3279.         if(fun!=-1)
  3280.             format_region(f,-1,fun);
  3281.          else /* if(main_map[c]!=BREAK_CMD) */
  3282.             error_msg("Unknown Justify '%s'",char_to_string(c));
  3283.         break;
  3284.  
  3285.     case 'p':
  3286.     case 'P':
  3287.         c=get_chr_prompt("[D]efault, [P]rotect, or [U]nprotect");
  3288.         if(c=='d' || c=='D')
  3289.             lock_region(f,LCK_DEF);
  3290.         else if(c=='p' || c=='P')
  3291.             lock_region(f,LCK_LCK);
  3292.         else if(c=='u' || c=='U')
  3293.             lock_region(f,LCK_UNL);
  3294.         else /* if(main_map[c]!=BREAK_CMD) */
  3295.             error_msg("Unknown lock %s",char_to_string(c));
  3296.         break;
  3297.  
  3298.     case 'w':
  3299.     case 'W':
  3300.         if(get_inp_line("set-width",&wid_line))
  3301.             break;
  3302.         ptr=wid_line.buf;
  3303.         if(*ptr=='d' || *ptr=='D')
  3304.             fun=0;
  3305.         else if(isdigit(*ptr))
  3306.             fun=astol(&ptr)+1;
  3307.         else {
  3308.             error_msg("Unknown width '%s'",wid_line.buf);
  3309.             break;
  3310.         }
  3311.         for(cc=f->lc;;cc++) {
  3312.             set_width(cc,fun);
  3313.             if(cc==f->hc)
  3314.                 break;
  3315.         }
  3316.         recenter_all_win();
  3317.         return;
  3318.  
  3319.     default:
  3320.         /* if(main_map[fun]!=BREAK_CMD) */
  3321.             error_msg("Unknown command '%s'",char_to_string(fun));
  3322.         break;
  3323.     }
  3324.     cur_status();
  3325.     /* topclear=2; */
  3326. }
  3327.  
  3328.  
  3329. void
  3330. got_sig FUN0()
  3331. {
  3332.     FILE *fp;
  3333.     extern int write();
  3334.  
  3335.     /* Using xopen_with_backup is almost certainly a bad idea, however
  3336.        using open() (preferred) or fopen() causes trouble in the restore,
  3337.        so we suffer. . . */
  3338.  
  3339.     fp=xopen_with_backup("oleo.panic","w");
  3340.     if(fp) {
  3341.         write(1,"Performing panic save to 'oleo.panic'\r\n",39);
  3342.         panic_write_file(fp,0);
  3343.         xclose(fp);
  3344.     } else
  3345.         write(1,"Can't open 'oleo.panic'!  You lose!\r\n",37);
  3346.     close_display();
  3347. #ifdef FASYNC
  3348.     fcntl(0,F_SETFL,term_flag);
  3349. #endif
  3350. #ifdef FIOSSAIOSTAT
  3351.     if((term_flag&1)==0) {
  3352.         int i=0;
  3353.  
  3354.         ioctl(0,FIOSSAIOSTAT,&i);
  3355.     }
  3356.     if((term_flag&2)==0) {
  3357.         int i=0;
  3358.  
  3359.         ioctl(0,FIOSNBIO,&i);
  3360.     }
  3361. #endif
  3362.  
  3363.     exit(11);
  3364. }
  3365.  
  3366. static void
  3367. got_sigint FUN1(int, ign)
  3368. {
  3369.     int ch;
  3370.  
  3371.     ch=get_chr_prompt("Panic save and exit?");
  3372.     if(ch=='y' || ch=='Y')
  3373.         got_sig();
  3374. }
  3375.  
  3376.  
  3377. static void
  3378. start_macro FUN0()
  3379. {
  3380.     if(making_macro) {
  3381.         error_msg("Can't define two macros at once");
  3382.         return;
  3383.     }
  3384.     making_macro_size=20;
  3385.     making_macro=making_macro_start=ck_malloc(5+making_macro_size);
  3386.     /* *making_macro++='"'; */
  3387. }
  3388.  
  3389. static void
  3390. end_macro FUN0()
  3391. {
  3392.     union vals z;
  3393.     struct rng to;
  3394.     CELL *cp;
  3395.     struct macro *old;
  3396.     static struct line macro_line;
  3397.  
  3398.     if(!rmac && !making_macro) {
  3399.         error_msg("Not executing or defining a macro!");
  3400.         return;
  3401.     }
  3402.     if(rmac) {
  3403.         if(rmac->mac_row==rmac->mac_rng.hr && rmac->mac_col==rmac->mac_rng.hc) {
  3404.             old=rmac->mac_prev;
  3405.             (void)obstack_free(¯o_stack,rmac);
  3406.             rmac=old;
  3407.             goto deal_making;
  3408.         }
  3409.  
  3410.         if(rmac->mac_row==rmac->mac_rng.hr) {
  3411.             rmac->mac_row=rmac->mac_rng.lr;
  3412.             rmac->mac_col++;
  3413.         } else
  3414.             rmac->mac_row++;
  3415.         if(!(cp=find_cell(rmac->mac_row,rmac->mac_col)) || GET_TYP(cp)!=TYP_STR || cp->cell_str[0]=='\0') {
  3416.             old=rmac->mac_prev;
  3417.             (void)obstack_free(¯o_stack,rmac);
  3418.             rmac=old;
  3419.             goto deal_making;
  3420.         }
  3421.         (void)obstack_grow(¯o_stack,cp->cell_str,1+strlen(cp->cell_str));
  3422.         rmac->mac_exe=(unsigned char *)obstack_finish(¯o_stack);
  3423.         rmac->mac_flags=0;
  3424.     }
  3425.  deal_making:
  3426.     if(!making_macro)
  3427.         return;
  3428.  
  3429.  
  3430.     making_macro[0]='\0';
  3431.     making_macro=0;
  3432.     if(get_a_range("Put macro where",&to,¯o_line))
  3433.         error_msg("Forgetting new macro");
  3434.     else {
  3435.         extern void set_new_value();
  3436.             z.c_s=(char *)making_macro_start;
  3437.         set_new_value(to.lr,to.lc,TYP_STR,&z);
  3438.     }
  3439.     free(making_macro_start);
  3440. }
  3441.  
  3442. static void
  3443. quit_cmd FUN0()
  3444. {
  3445.     int c;
  3446.  
  3447.     close_display();
  3448. #ifndef AMIGA
  3449. #ifdef FASYNC
  3450.     c=fcntl(0,F_SETFL,term_flag);
  3451. #endif
  3452. #ifdef FIOSSAIOSTAT
  3453.     if((term_flag&1)==0) {
  3454.         int i=0;
  3455.  
  3456.         ioctl(0,FIOSSAIOSTAT,&i);
  3457.     }
  3458.     if((term_flag&2)==0) {
  3459.         int i=0;
  3460.  
  3461.         ioctl(0,FIOSNBIO,&i);
  3462.     }
  3463. #endif
  3464. #endif
  3465.     exit(0);
  3466. }
  3467.  
  3468. static void
  3469. bound_macro FUN1(int, num)
  3470. {
  3471.     struct macro *old;
  3472.     CELL *cp;
  3473.     /* CELLREF rr,cc; */
  3474.  
  3475.     cp=find_cell(bound_macros[num].lr,bound_macros[num].lc);
  3476.     if(!cp || GET_TYP(cp)!=TYP_STR || cp->cell_str[0]=='\0')
  3477.         return;
  3478.     old=rmac;
  3479.     rmac=(struct macro *)obstack_alloc(¯o_stack,sizeof(struct macro));
  3480.     rmac->mac_prev=old;
  3481.     rmac->mac_rng=bound_macros[num];
  3482.     rmac->mac_row=bound_macros[num].lr;
  3483.     rmac->mac_col=bound_macros[num].lc;
  3484.     (void)obstack_grow(¯o_stack,cp->cell_str,1+strlen(cp->cell_str));
  3485.     rmac->mac_exe=(unsigned char *)obstack_finish(¯o_stack);
  3486.     rmac->mac_flags=0;
  3487. }
  3488.  
  3489. static void
  3490. mark_cell_cmd FUN0()
  3491. {
  3492.     mkrow=curow;
  3493.     mkcol=cucol;
  3494.     cur_status();
  3495. }
  3496.  
  3497. static void
  3498. recalc_cmd FUN0()
  3499. {
  3500.     current_cycle++;
  3501.     while(eval_next_cell())
  3502.         ;
  3503. }
  3504.  
  3505. static void
  3506. desc_key_cmd FUN0()
  3507. {
  3508.     error_msg("Key:  ");
  3509.     map_chr(MAIN_MAP);
  3510.     if(!cur_cmd)
  3511.         info_msg("%s is unbound", char_to_string(cur_chr));
  3512.     else
  3513.         info_msg("%s --> %s",char_to_string(cur_chr), cur_cmd->func_name);
  3514. }
  3515.  
  3516. static void
  3517. bind_key_cmd FUN1(char *,text)
  3518. {
  3519.     int map;
  3520.     int c;
  3521.     /* int n; */
  3522.     int vec;
  3523.     int code;
  3524.     char *ptr;
  3525.     char *cmdstr;
  3526.     struct rng rng;
  3527.     struct cmd_func *tmpfunc;
  3528.     static struct line tmpline;
  3529.  
  3530.     for(ptr=text;*ptr && *ptr!=' ';ptr++)
  3531.         ;
  3532.     if(!*ptr) {
  3533.         if(get_inp_line("Command",&tmpline))
  3534.             return;
  3535.         ptr=tmpline.buf;
  3536.     } else
  3537.         *ptr++='\0';
  3538.     while(*ptr==' ')
  3539.         ptr++;
  3540.     cmdstr=ptr;
  3541.     while(*ptr && *ptr!=' ')
  3542.         ptr++;
  3543.     if(!*ptr)
  3544.         c=get_chr_prompt("Key:  ");
  3545.     else {
  3546.         *ptr++='\0';
  3547.         c=string_to_char(&ptr);
  3548.     }
  3549.  
  3550.     for(map=0;map<num_maps;map++)
  3551.         if(!strcmp(text,map_names[map]))
  3552.             break;
  3553.     if(map==num_maps) {
  3554.         error_msg("Can't find keymap '%s'",text);
  3555.         goto fail;
  3556.     }
  3557.     for(vec=0;vec<num_funcs;vec++) {
  3558.         for(code=0;the_funcs[vec][code].func_name;code++)
  3559.             if(!stricmp(cmdstr,the_funcs[vec][code].func_name))
  3560.                 goto fini;
  3561.     }
  3562.     for(code=0;code<num_maps;code++) {
  3563.         if(!strcmp(cmdstr,map_names[code])) {
  3564.             vec=255;
  3565.             goto fini;
  3566.         }
  3567.     }
  3568.     if(get_abs_rng(&cmdstr,&rng)) {
  3569.         error_msg("Unknown command '%s'",cmdstr);
  3570.         goto fail;
  3571.     }
  3572.  
  3573.     vec=bound_macro_vec;
  3574.     for(code=0;code<n_bound_macros;code++) {
  3575.         if(!bcmp(&bound_macros[code],&rng,sizeof(struct rng)))
  3576.             goto fini;
  3577.     }
  3578.  
  3579.     ptr=range_name(&rng);
  3580.     if(!bound_macro_vec) {
  3581.         bound_macros=ck_malloc(sizeof(struct rng));
  3582.         n_bound_macros=1;
  3583.         tmpfunc=ck_malloc(sizeof(struct cmd_func));
  3584.         bound_macro_vec=add_usr_cmds(tmpfunc);
  3585.     } else {
  3586.         n_bound_macros++;
  3587.  
  3588.         bound_macros=ck_realloc(bound_macros,n_bound_macros*sizeof(struct rng));
  3589.  
  3590.         the_funcs[bound_macro_vec]=ck_realloc(the_funcs[bound_macro_vec],n_bound_macros*sizeof(struct cmd_func));
  3591.         tmpfunc= &the_funcs[bound_macro_vec][n_bound_macros-1];
  3592.     }
  3593.     bound_macros[n_bound_macros-1]=rng;
  3594.     tmpfunc->func_args=ck_malloc(strlen(ptr)+5);
  3595.     tmpfunc->func_args[0]='n';
  3596.     tmpfunc->func_args[1]='a'+(n_bound_macros-1)/26;
  3597.     tmpfunc->func_args[2]='a'+(n_bound_macros-1)%26;
  3598.     tmpfunc->func_args[3]='\0';
  3599.     tmpfunc->func_name=tmpfunc->func_args+4;
  3600.     strcpy(tmpfunc->func_name,ptr);
  3601.     tmpfunc->func_flags=ALL;
  3602.     tmpfunc->func_func=bound_macro;
  3603.  fini:
  3604.     do_bind_key(the_maps[map],c,vec,code);
  3605.  fail:
  3606.     sprint_line(&in_line[16],"%s %s %s",text,cmdstr,char_to_string(c));
  3607. }
  3608.  
  3609. static void
  3610. do_bind_key FUN4(struct keymap *,map, int,key, unsigned char,vector, unsigned char,code)
  3611. {
  3612.     struct keymap *m;
  3613.     struct key *k;
  3614.     int n;
  3615.  
  3616.  
  3617.     for(m=map;m;m=m->map_next) {
  3618.         if(key+1>=m->lochr && key-1<=m->hichr)
  3619.             break;
  3620.         if(m->map_end)
  3621.             m=0;
  3622.     }
  3623.     if(m->map_dense) {
  3624.         if(vector==m->keys[0].vector && code==m->keys[0].code) {
  3625.             if(key<m->lochr)
  3626.                 m->lochr=key;
  3627.             if(key>m->hichr)
  3628.                 m->hichr=key;
  3629.             return;
  3630.         } else if(m->lochr!=m->hichr)
  3631.             m=0;
  3632.         else
  3633.             m->map_dense=0;
  3634.     }
  3635.     if(m==0) {
  3636.         m=ck_malloc(sizeof(struct keymap));
  3637.         *m= *map;
  3638.         map->map_next=m;
  3639.         m=map;
  3640.         m->map_end=0;
  3641.         m->map_dense=1;
  3642.         m->map_malloc=2;
  3643.         m->lochr=key;
  3644.         m->hichr=key;
  3645.         m->keys=ck_malloc(sizeof(struct key));
  3646.     }
  3647.     if(key<m->lochr) {
  3648.         n=sizeof(struct key)*(1+m->hichr-m->lochr);
  3649.         k=ck_malloc(n+sizeof(struct key));
  3650.         bcopy(&m->keys[0],&k[1],n);
  3651.         if(m->map_malloc==2)
  3652.             free(m->keys);
  3653.         m->keys=k;
  3654.         m->lochr=key;
  3655.         m->map_malloc=2;
  3656.     }
  3657.     if(key>m->hichr) {
  3658.         if(m->map_malloc==2)
  3659.           {
  3660.  
  3661.             m->keys=ck_realloc(m->keys,sizeof(struct key)*(1+m->hichr-m->lochr));
  3662. }
  3663.         else {
  3664.             n=sizeof(struct key)*(1+m->hichr-m->lochr);
  3665.             k=ck_malloc(n+sizeof(struct key));
  3666.             bcopy(&m->keys[0],k,n);
  3667.             m->keys=k;
  3668.             m->map_malloc=2;
  3669.         }
  3670.         m->hichr=key;
  3671.     }
  3672.     if(!m->map_malloc) {
  3673.         n=sizeof(struct key)*(1+m->hichr-m->lochr);
  3674.         k=ck_malloc(n);
  3675.         bcopy(&m->keys[0],k,n);
  3676.         m->keys=k;
  3677.         m->map_malloc=2;
  3678.     }
  3679.     m->keys[key-m->lochr].vector=vector;
  3680.     m->keys[key-m->lochr].code=code;
  3681. }
  3682.  
  3683. static void
  3684. interact_macro_cmd FUN0()
  3685. {
  3686.     error_msg("Command not implemented");
  3687.     return;
  3688. }
  3689.  
  3690. static void
  3691. kill_cell_cmd FUN0()
  3692. {
  3693.     CELL *cp;
  3694.  
  3695.     cp=find_cell(curow,cucol);
  3696.     if(!cp)
  3697.         return;
  3698.     if((GET_LCK(cp)==LCK_DEF && default_lock==LCK_LCK) || GET_LCK(cp)==LCK_LCK) {
  3699.         error_msg("Cell %s is locked",cell_name(curow,cucol));
  3700.         return;
  3701.     }
  3702.     new_value(curow,cucol,"");
  3703.     cp->cell_flags=0;
  3704.     modified=1;
  3705. }
  3706.  
  3707. static void
  3708. format_cell_cmd FUN0()
  3709. {
  3710.     struct rng to;
  3711.  
  3712.     to.lr=to.hr=curow;
  3713.     to.lc=to.hc=cucol;
  3714.     format_area(&to);
  3715. }
  3716.  
  3717. static void
  3718. kill_all_cmd FUN0()
  3719. {
  3720.     clear_spreadsheet();
  3721.     disp_scrn();
  3722. }
  3723.  
  3724. #if 0
  3725. static void
  3726. do_ansi_cmd FUN0()
  3727. {
  3728.     int c;
  3729.  
  3730.     c=get_chr();
  3731.     if(c>='A' && c<='D')
  3732.         shift_cell_cursor(c-'A');
  3733.     else
  3734.         /* ? ? ? */;
  3735. }
  3736. #endif
  3737.  
  3738. static void
  3739. do_input_cmd FUN2(int, n, int,c)
  3740. {
  3741.     CELL *cp;
  3742.     char *fail;
  3743.  
  3744.     extern char *cell_value_string EXT2(CELLREF, CELLREF);
  3745.  
  3746.     switch(n) {
  3747.         /* Edit cell */
  3748.     case 0:
  3749.         if(cp=find_cell(curow,cucol)) {
  3750.             set_line(&val_line,decomp(curow,cucol,cp));
  3751.             decomp_free();
  3752.         } else
  3753.             set_line(&val_line,0);
  3754.         break;
  3755.  
  3756.         /* Edit Cell Value */
  3757.     case 1:
  3758.         set_line(&val_line,cell_value_string(curow,cucol));
  3759.         break;
  3760.  
  3761.     case 2:    /* Set-cell */
  3762.         set_line(&val_line,"x");
  3763.         val_line.buf[0]=c;
  3764.         break;
  3765.  
  3766.         /* New Def Cell */
  3767.     case 3:
  3768.         break;
  3769. #ifdef TEST
  3770.     default:
  3771.         panic("Unknown value in do_input_cell (%d)",n);
  3772. #endif
  3773.     }
  3774.     cp=find_cell(curow,cucol);
  3775.     if(((!cp || GET_LCK(cp)==LCK_DEF) && default_lock==LCK_LCK) || (cp && GET_LCK(cp)==LCK_LCK)) {
  3776.         error_msg("Cell %s is locked",cell_name(curow,cucol));
  3777.         return;
  3778.     }
  3779.     setrow=curow;
  3780.     setcol=cucol;
  3781.     if(get_inp_line("set-cell",&val_line)>1)
  3782.         return;
  3783.     fail=new_value(setrow,setcol,val_line.buf);
  3784.     if(fail)
  3785.         error_msg(fail);
  3786.     else
  3787.         modified=1;
  3788. }
  3789.  
  3790. static void
  3791. do_break_cmd FUN0()
  3792. {
  3793.     if(mkrow!=NON_ROW) {
  3794.         mkrow=NON_ROW;
  3795.         how_many=1;
  3796.         cur_status();
  3797.     }
  3798. }
  3799.  
  3800. static void
  3801. digit_cmd FUN1(int, magic)
  3802. {
  3803.     struct keymap *map;
  3804.  
  3805.     for(map=the_maps[DIGIT_MAP];map->map_end==0;map=map->map_next)
  3806.         ;
  3807.     map->map_next= the_maps[magic];
  3808.     how_many=0;
  3809.     do {
  3810.         how_many=how_many * 10 + cur_cmd - &cmd_funcs[DIGIT_0];
  3811.         cur_status();
  3812.         map_chr(DIGIT_MAP);
  3813.     } while(cur_cmd>= &cmd_funcs[DIGIT_0] && cur_cmd<= &cmd_funcs[DIGIT_9]);
  3814. }
  3815.  
  3816.  
  3817.